1 // __ _____ _____ _____ 2 // __| | __| | | | JSON for Modern C++ 3 // | | |__ | | | | | | version 3.11.3 4 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 5 // 6 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 7 // SPDX-License-Identifier: MIT 8 9 /****************************************************************************\ 10 * Note on documentation: The source files contain links to the online * 11 * documentation of the public API at https://json.nlohmann.me. This URL * 12 * contains the most recent documentation and should also be applicable to * 13 * previous versions; documentation for deprecated functions is not * 14 * removed, but marked deprecated. See "Generate documentation" section in * 15 * file docs/README.md. * 16 \****************************************************************************/ 17 18 #ifndef INCLUDE_NLOHMANN_JSON_HPP_ 19 #define INCLUDE_NLOHMANN_JSON_HPP_ 20 21 #include <algorithm> // all_of, find, for_each 22 #include <cstddef> // nullptr_t, ptrdiff_t, size_t 23 #include <functional> // hash, less 24 #include <initializer_list> // initializer_list 25 #ifndef JSON_NO_IO 26 #include <iosfwd> // istream, ostream 27 #endif // JSON_NO_IO 28 #include <iterator> // random_access_iterator_tag 29 #include <memory> // unique_ptr 30 #include <string> // string, stoi, to_string 31 #include <utility> // declval, forward, move, pair, swap 32 #include <vector> // vector 33 34 // #include <nlohmann/adl_serializer.hpp> 35 // __ _____ _____ _____ 36 // __| | __| | | | JSON for Modern C++ 37 // | | |__ | | | | | | version 3.11.3 38 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 39 // 40 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 41 // SPDX-License-Identifier: MIT 42 43 44 45 #include <utility> 46 47 // #include <nlohmann/detail/abi_macros.hpp> 48 // __ _____ _____ _____ 49 // __| | __| | | | JSON for Modern C++ 50 // | | |__ | | | | | | version 3.11.3 51 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 52 // 53 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 54 // SPDX-License-Identifier: MIT 55 56 57 58 // This file contains all macro definitions affecting or depending on the ABI 59 60 #ifndef JSON_SKIP_LIBRARY_VERSION_CHECK 61 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) 62 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3 63 #warning "Already included a different version of the library!" 64 #endif 65 #endif 66 #endif 67 68 #define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) 69 #define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) 70 #define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum) 71 72 #ifndef JSON_DIAGNOSTICS 73 #define JSON_DIAGNOSTICS 0 74 #endif 75 76 #ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 77 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 78 #endif 79 80 #if JSON_DIAGNOSTICS 81 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag 82 #else 83 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS 84 #endif 85 86 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 87 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp 88 #else 89 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON 90 #endif 91 92 #ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION 93 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 94 #endif 95 96 // Construct the namespace ABI tags component 97 #define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b 98 #define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ 99 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) 100 101 #define NLOHMANN_JSON_ABI_TAGS \ 102 NLOHMANN_JSON_ABI_TAGS_CONCAT( \ 103 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ 104 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) 105 106 // Construct the namespace version component 107 #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ 108 _v ## major ## _ ## minor ## _ ## patch 109 #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ 110 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) 111 112 #if NLOHMANN_JSON_NAMESPACE_NO_VERSION 113 #define NLOHMANN_JSON_NAMESPACE_VERSION 114 #else 115 #define NLOHMANN_JSON_NAMESPACE_VERSION \ 116 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ 117 NLOHMANN_JSON_VERSION_MINOR, \ 118 NLOHMANN_JSON_VERSION_PATCH) 119 #endif 120 121 // Combine namespace components 122 #define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b 123 #define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ 124 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) 125 126 #ifndef NLOHMANN_JSON_NAMESPACE 127 #define NLOHMANN_JSON_NAMESPACE \ 128 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ 129 NLOHMANN_JSON_ABI_TAGS, \ 130 NLOHMANN_JSON_NAMESPACE_VERSION) 131 #endif 132 133 #ifndef NLOHMANN_JSON_NAMESPACE_BEGIN 134 #define NLOHMANN_JSON_NAMESPACE_BEGIN \ 135 namespace nlohmann \ 136 { \ 137 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ 138 NLOHMANN_JSON_ABI_TAGS, \ 139 NLOHMANN_JSON_NAMESPACE_VERSION) \ 140 { 141 #endif 142 143 #ifndef NLOHMANN_JSON_NAMESPACE_END 144 #define NLOHMANN_JSON_NAMESPACE_END \ 145 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ 146 } // namespace nlohmann 147 #endif 148 149 // #include <nlohmann/detail/conversions/from_json.hpp> 150 // __ _____ _____ _____ 151 // __| | __| | | | JSON for Modern C++ 152 // | | |__ | | | | | | version 3.11.3 153 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 154 // 155 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 156 // SPDX-License-Identifier: MIT 157 158 159 160 #include <algorithm> // transform 161 #include <array> // array 162 #include <forward_list> // forward_list 163 #include <iterator> // inserter, front_inserter, end 164 #include <map> // map 165 #ifdef JSON_HAS_CPP_17 166 #include <optional> // optional 167 #endif 168 #include <string> // string 169 #include <tuple> // tuple, make_tuple 170 #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible 171 #include <unordered_map> // unordered_map 172 #include <utility> // pair, declval 173 #include <valarray> // valarray 174 175 176 // #include <nlohmann/detail/exceptions.hpp> 177 // __ _____ _____ _____ 178 // __| | __| | | | JSON for Modern C++ 179 // | | |__ | | | | | | version 3.11.3 180 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 181 // 182 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 183 // SPDX-License-Identifier: MIT 184 185 186 187 #include <cstddef> // nullptr_t 188 #include <exception> // exception 189 #if JSON_DIAGNOSTICS 190 #include <numeric> // accumulate 191 #endif 192 #include <stdexcept> // runtime_error 193 #include <string> // to_string 194 #include <vector> // vector 195 196 // #include <nlohmann/detail/value_t.hpp> 197 // __ _____ _____ _____ 198 // __| | __| | | | JSON for Modern C++ 199 // | | |__ | | | | | | version 3.11.3 200 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 201 // 202 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 203 // SPDX-License-Identifier: MIT 204 205 206 207 #include <array> // array 208 #include <cstddef> // size_t 209 #include <cstdint> // uint8_t 210 #include <string> // string 211 212 // #include <nlohmann/detail/macro_scope.hpp> 213 // __ _____ _____ _____ 214 // __| | __| | | | JSON for Modern C++ 215 // | | |__ | | | | | | version 3.11.3 216 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 217 // 218 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 219 // SPDX-License-Identifier: MIT 220 221 222 223 #include <utility> // declval, pair 224 // #include <nlohmann/detail/meta/detected.hpp> 225 // __ _____ _____ _____ 226 // __| | __| | | | JSON for Modern C++ 227 // | | |__ | | | | | | version 3.11.3 228 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 229 // 230 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 231 // SPDX-License-Identifier: MIT 232 233 234 235 #include <type_traits> 236 237 // #include <nlohmann/detail/meta/void_t.hpp> 238 // __ _____ _____ _____ 239 // __| | __| | | | JSON for Modern C++ 240 // | | |__ | | | | | | version 3.11.3 241 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 242 // 243 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 244 // SPDX-License-Identifier: MIT 245 246 247 248 // #include <nlohmann/detail/abi_macros.hpp> 249 250 251 NLOHMANN_JSON_NAMESPACE_BEGIN 252 namespace detail 253 { 254 255 template<typename ...Ts> struct make_void 256 { 257 using type = void; 258 }; 259 template<typename ...Ts> using void_t = typename make_void<Ts...>::type; 260 261 } // namespace detail 262 NLOHMANN_JSON_NAMESPACE_END 263 264 265 NLOHMANN_JSON_NAMESPACE_BEGIN 266 namespace detail 267 { 268 269 // https://en.cppreference.com/w/cpp/experimental/is_detected 270 struct nonesuch 271 { 272 nonesuch() = delete; 273 ~nonesuch() = delete; 274 nonesuch(nonesuch const&) = delete; 275 nonesuch(nonesuch const&&) = delete; 276 void operator=(nonesuch const&) = delete; 277 void operator=(nonesuch&&) = delete; 278 }; 279 280 template<class Default, 281 class AlwaysVoid, 282 template<class...> class Op, 283 class... Args> 284 struct detector 285 { 286 using value_t = std::false_type; 287 using type = Default; 288 }; 289 290 template<class Default, template<class...> class Op, class... Args> 291 struct detector<Default, void_t<Op<Args...>>, Op, Args...> 292 { 293 using value_t = std::true_type; 294 using type = Op<Args...>; 295 }; 296 297 template<template<class...> class Op, class... Args> 298 using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t; 299 300 template<template<class...> class Op, class... Args> 301 struct is_detected_lazy : is_detected<Op, Args...> { }; 302 303 template<template<class...> class Op, class... Args> 304 using detected_t = typename detector<nonesuch, void, Op, Args...>::type; 305 306 template<class Default, template<class...> class Op, class... Args> 307 using detected_or = detector<Default, void, Op, Args...>; 308 309 template<class Default, template<class...> class Op, class... Args> 310 using detected_or_t = typename detected_or<Default, Op, Args...>::type; 311 312 template<class Expected, template<class...> class Op, class... Args> 313 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>; 314 315 template<class To, template<class...> class Op, class... Args> 316 using is_detected_convertible = 317 std::is_convertible<detected_t<Op, Args...>, To>; 318 319 } // namespace detail 320 NLOHMANN_JSON_NAMESPACE_END 321 322 // #include <nlohmann/thirdparty/hedley/hedley.hpp> 323 324 325 // __ _____ _____ _____ 326 // __| | __| | | | JSON for Modern C++ 327 // | | |__ | | | | | | version 3.11.3 328 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 329 // 330 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 331 // SPDX-FileCopyrightText: 2016 - 2021 Evan Nemerson <evan@nemerson.com> 332 // SPDX-License-Identifier: MIT 333 334 /* Hedley - https://nemequ.github.io/hedley 335 * Created by Evan Nemerson <evan@nemerson.com> 336 */ 337 338 #if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) 339 #if defined(JSON_HEDLEY_VERSION) 340 #undef JSON_HEDLEY_VERSION 341 #endif 342 #define JSON_HEDLEY_VERSION 15 343 344 #if defined(JSON_HEDLEY_STRINGIFY_EX) 345 #undef JSON_HEDLEY_STRINGIFY_EX 346 #endif 347 #define JSON_HEDLEY_STRINGIFY_EX(x) #x 348 349 #if defined(JSON_HEDLEY_STRINGIFY) 350 #undef JSON_HEDLEY_STRINGIFY 351 #endif 352 #define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) 353 354 #if defined(JSON_HEDLEY_CONCAT_EX) 355 #undef JSON_HEDLEY_CONCAT_EX 356 #endif 357 #define JSON_HEDLEY_CONCAT_EX(a,b) a##b 358 359 #if defined(JSON_HEDLEY_CONCAT) 360 #undef JSON_HEDLEY_CONCAT 361 #endif 362 #define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) 363 364 #if defined(JSON_HEDLEY_CONCAT3_EX) 365 #undef JSON_HEDLEY_CONCAT3_EX 366 #endif 367 #define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c 368 369 #if defined(JSON_HEDLEY_CONCAT3) 370 #undef JSON_HEDLEY_CONCAT3 371 #endif 372 #define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) 373 374 #if defined(JSON_HEDLEY_VERSION_ENCODE) 375 #undef JSON_HEDLEY_VERSION_ENCODE 376 #endif 377 #define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) 378 379 #if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) 380 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR 381 #endif 382 #define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) 383 384 #if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) 385 #undef JSON_HEDLEY_VERSION_DECODE_MINOR 386 #endif 387 #define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) 388 389 #if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) 390 #undef JSON_HEDLEY_VERSION_DECODE_REVISION 391 #endif 392 #define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) 393 394 #if defined(JSON_HEDLEY_GNUC_VERSION) 395 #undef JSON_HEDLEY_GNUC_VERSION 396 #endif 397 #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) 398 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) 399 #elif defined(__GNUC__) 400 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) 401 #endif 402 403 #if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) 404 #undef JSON_HEDLEY_GNUC_VERSION_CHECK 405 #endif 406 #if defined(JSON_HEDLEY_GNUC_VERSION) 407 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 408 #else 409 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) 410 #endif 411 412 #if defined(JSON_HEDLEY_MSVC_VERSION) 413 #undef JSON_HEDLEY_MSVC_VERSION 414 #endif 415 #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) 416 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) 417 #elif defined(_MSC_FULL_VER) && !defined(__ICL) 418 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) 419 #elif defined(_MSC_VER) && !defined(__ICL) 420 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) 421 #endif 422 423 #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) 424 #undef JSON_HEDLEY_MSVC_VERSION_CHECK 425 #endif 426 #if !defined(JSON_HEDLEY_MSVC_VERSION) 427 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) 428 #elif defined(_MSC_VER) && (_MSC_VER >= 1400) 429 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) 430 #elif defined(_MSC_VER) && (_MSC_VER >= 1200) 431 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) 432 #else 433 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) 434 #endif 435 436 #if defined(JSON_HEDLEY_INTEL_VERSION) 437 #undef JSON_HEDLEY_INTEL_VERSION 438 #endif 439 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) 440 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) 441 #elif defined(__INTEL_COMPILER) && !defined(__ICL) 442 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) 443 #endif 444 445 #if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) 446 #undef JSON_HEDLEY_INTEL_VERSION_CHECK 447 #endif 448 #if defined(JSON_HEDLEY_INTEL_VERSION) 449 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 450 #else 451 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) 452 #endif 453 454 #if defined(JSON_HEDLEY_INTEL_CL_VERSION) 455 #undef JSON_HEDLEY_INTEL_CL_VERSION 456 #endif 457 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) 458 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) 459 #endif 460 461 #if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) 462 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK 463 #endif 464 #if defined(JSON_HEDLEY_INTEL_CL_VERSION) 465 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 466 #else 467 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) 468 #endif 469 470 #if defined(JSON_HEDLEY_PGI_VERSION) 471 #undef JSON_HEDLEY_PGI_VERSION 472 #endif 473 #if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) 474 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) 475 #endif 476 477 #if defined(JSON_HEDLEY_PGI_VERSION_CHECK) 478 #undef JSON_HEDLEY_PGI_VERSION_CHECK 479 #endif 480 #if defined(JSON_HEDLEY_PGI_VERSION) 481 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 482 #else 483 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) 484 #endif 485 486 #if defined(JSON_HEDLEY_SUNPRO_VERSION) 487 #undef JSON_HEDLEY_SUNPRO_VERSION 488 #endif 489 #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) 490 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) 491 #elif defined(__SUNPRO_C) 492 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) 493 #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) 494 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) 495 #elif defined(__SUNPRO_CC) 496 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) 497 #endif 498 499 #if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) 500 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK 501 #endif 502 #if defined(JSON_HEDLEY_SUNPRO_VERSION) 503 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 504 #else 505 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) 506 #endif 507 508 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) 509 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION 510 #endif 511 #if defined(__EMSCRIPTEN__) 512 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) 513 #endif 514 515 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) 516 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK 517 #endif 518 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) 519 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 520 #else 521 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) 522 #endif 523 524 #if defined(JSON_HEDLEY_ARM_VERSION) 525 #undef JSON_HEDLEY_ARM_VERSION 526 #endif 527 #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) 528 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) 529 #elif defined(__CC_ARM) && defined(__ARMCC_VERSION) 530 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) 531 #endif 532 533 #if defined(JSON_HEDLEY_ARM_VERSION_CHECK) 534 #undef JSON_HEDLEY_ARM_VERSION_CHECK 535 #endif 536 #if defined(JSON_HEDLEY_ARM_VERSION) 537 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 538 #else 539 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) 540 #endif 541 542 #if defined(JSON_HEDLEY_IBM_VERSION) 543 #undef JSON_HEDLEY_IBM_VERSION 544 #endif 545 #if defined(__ibmxl__) 546 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) 547 #elif defined(__xlC__) && defined(__xlC_ver__) 548 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) 549 #elif defined(__xlC__) 550 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) 551 #endif 552 553 #if defined(JSON_HEDLEY_IBM_VERSION_CHECK) 554 #undef JSON_HEDLEY_IBM_VERSION_CHECK 555 #endif 556 #if defined(JSON_HEDLEY_IBM_VERSION) 557 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 558 #else 559 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) 560 #endif 561 562 #if defined(JSON_HEDLEY_TI_VERSION) 563 #undef JSON_HEDLEY_TI_VERSION 564 #endif 565 #if \ 566 defined(__TI_COMPILER_VERSION__) && \ 567 ( \ 568 defined(__TMS470__) || defined(__TI_ARM__) || \ 569 defined(__MSP430__) || \ 570 defined(__TMS320C2000__) \ 571 ) 572 #if (__TI_COMPILER_VERSION__ >= 16000000) 573 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 574 #endif 575 #endif 576 577 #if defined(JSON_HEDLEY_TI_VERSION_CHECK) 578 #undef JSON_HEDLEY_TI_VERSION_CHECK 579 #endif 580 #if defined(JSON_HEDLEY_TI_VERSION) 581 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 582 #else 583 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) 584 #endif 585 586 #if defined(JSON_HEDLEY_TI_CL2000_VERSION) 587 #undef JSON_HEDLEY_TI_CL2000_VERSION 588 #endif 589 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) 590 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 591 #endif 592 593 #if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) 594 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK 595 #endif 596 #if defined(JSON_HEDLEY_TI_CL2000_VERSION) 597 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 598 #else 599 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) 600 #endif 601 602 #if defined(JSON_HEDLEY_TI_CL430_VERSION) 603 #undef JSON_HEDLEY_TI_CL430_VERSION 604 #endif 605 #if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) 606 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 607 #endif 608 609 #if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) 610 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK 611 #endif 612 #if defined(JSON_HEDLEY_TI_CL430_VERSION) 613 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 614 #else 615 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) 616 #endif 617 618 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION) 619 #undef JSON_HEDLEY_TI_ARMCL_VERSION 620 #endif 621 #if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) 622 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 623 #endif 624 625 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) 626 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK 627 #endif 628 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION) 629 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 630 #else 631 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) 632 #endif 633 634 #if defined(JSON_HEDLEY_TI_CL6X_VERSION) 635 #undef JSON_HEDLEY_TI_CL6X_VERSION 636 #endif 637 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) 638 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 639 #endif 640 641 #if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) 642 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK 643 #endif 644 #if defined(JSON_HEDLEY_TI_CL6X_VERSION) 645 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 646 #else 647 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) 648 #endif 649 650 #if defined(JSON_HEDLEY_TI_CL7X_VERSION) 651 #undef JSON_HEDLEY_TI_CL7X_VERSION 652 #endif 653 #if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) 654 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 655 #endif 656 657 #if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) 658 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK 659 #endif 660 #if defined(JSON_HEDLEY_TI_CL7X_VERSION) 661 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 662 #else 663 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) 664 #endif 665 666 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION) 667 #undef JSON_HEDLEY_TI_CLPRU_VERSION 668 #endif 669 #if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) 670 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 671 #endif 672 673 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) 674 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK 675 #endif 676 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION) 677 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 678 #else 679 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) 680 #endif 681 682 #if defined(JSON_HEDLEY_CRAY_VERSION) 683 #undef JSON_HEDLEY_CRAY_VERSION 684 #endif 685 #if defined(_CRAYC) 686 #if defined(_RELEASE_PATCHLEVEL) 687 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) 688 #else 689 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) 690 #endif 691 #endif 692 693 #if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) 694 #undef JSON_HEDLEY_CRAY_VERSION_CHECK 695 #endif 696 #if defined(JSON_HEDLEY_CRAY_VERSION) 697 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 698 #else 699 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) 700 #endif 701 702 #if defined(JSON_HEDLEY_IAR_VERSION) 703 #undef JSON_HEDLEY_IAR_VERSION 704 #endif 705 #if defined(__IAR_SYSTEMS_ICC__) 706 #if __VER__ > 1000 707 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) 708 #else 709 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) 710 #endif 711 #endif 712 713 #if defined(JSON_HEDLEY_IAR_VERSION_CHECK) 714 #undef JSON_HEDLEY_IAR_VERSION_CHECK 715 #endif 716 #if defined(JSON_HEDLEY_IAR_VERSION) 717 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 718 #else 719 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) 720 #endif 721 722 #if defined(JSON_HEDLEY_TINYC_VERSION) 723 #undef JSON_HEDLEY_TINYC_VERSION 724 #endif 725 #if defined(__TINYC__) 726 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) 727 #endif 728 729 #if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) 730 #undef JSON_HEDLEY_TINYC_VERSION_CHECK 731 #endif 732 #if defined(JSON_HEDLEY_TINYC_VERSION) 733 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 734 #else 735 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) 736 #endif 737 738 #if defined(JSON_HEDLEY_DMC_VERSION) 739 #undef JSON_HEDLEY_DMC_VERSION 740 #endif 741 #if defined(__DMC__) 742 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) 743 #endif 744 745 #if defined(JSON_HEDLEY_DMC_VERSION_CHECK) 746 #undef JSON_HEDLEY_DMC_VERSION_CHECK 747 #endif 748 #if defined(JSON_HEDLEY_DMC_VERSION) 749 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 750 #else 751 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) 752 #endif 753 754 #if defined(JSON_HEDLEY_COMPCERT_VERSION) 755 #undef JSON_HEDLEY_COMPCERT_VERSION 756 #endif 757 #if defined(__COMPCERT_VERSION__) 758 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) 759 #endif 760 761 #if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) 762 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK 763 #endif 764 #if defined(JSON_HEDLEY_COMPCERT_VERSION) 765 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 766 #else 767 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) 768 #endif 769 770 #if defined(JSON_HEDLEY_PELLES_VERSION) 771 #undef JSON_HEDLEY_PELLES_VERSION 772 #endif 773 #if defined(__POCC__) 774 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) 775 #endif 776 777 #if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) 778 #undef JSON_HEDLEY_PELLES_VERSION_CHECK 779 #endif 780 #if defined(JSON_HEDLEY_PELLES_VERSION) 781 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 782 #else 783 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) 784 #endif 785 786 #if defined(JSON_HEDLEY_MCST_LCC_VERSION) 787 #undef JSON_HEDLEY_MCST_LCC_VERSION 788 #endif 789 #if defined(__LCC__) && defined(__LCC_MINOR__) 790 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) 791 #endif 792 793 #if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) 794 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK 795 #endif 796 #if defined(JSON_HEDLEY_MCST_LCC_VERSION) 797 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 798 #else 799 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) 800 #endif 801 802 #if defined(JSON_HEDLEY_GCC_VERSION) 803 #undef JSON_HEDLEY_GCC_VERSION 804 #endif 805 #if \ 806 defined(JSON_HEDLEY_GNUC_VERSION) && \ 807 !defined(__clang__) && \ 808 !defined(JSON_HEDLEY_INTEL_VERSION) && \ 809 !defined(JSON_HEDLEY_PGI_VERSION) && \ 810 !defined(JSON_HEDLEY_ARM_VERSION) && \ 811 !defined(JSON_HEDLEY_CRAY_VERSION) && \ 812 !defined(JSON_HEDLEY_TI_VERSION) && \ 813 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ 814 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ 815 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ 816 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ 817 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ 818 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ 819 !defined(__COMPCERT__) && \ 820 !defined(JSON_HEDLEY_MCST_LCC_VERSION) 821 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION 822 #endif 823 824 #if defined(JSON_HEDLEY_GCC_VERSION_CHECK) 825 #undef JSON_HEDLEY_GCC_VERSION_CHECK 826 #endif 827 #if defined(JSON_HEDLEY_GCC_VERSION) 828 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 829 #else 830 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) 831 #endif 832 833 #if defined(JSON_HEDLEY_HAS_ATTRIBUTE) 834 #undef JSON_HEDLEY_HAS_ATTRIBUTE 835 #endif 836 #if \ 837 defined(__has_attribute) && \ 838 ( \ 839 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ 840 ) 841 # define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) 842 #else 843 # define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) 844 #endif 845 846 #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) 847 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE 848 #endif 849 #if defined(__has_attribute) 850 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) 851 #else 852 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 853 #endif 854 855 #if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) 856 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE 857 #endif 858 #if defined(__has_attribute) 859 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) 860 #else 861 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 862 #endif 863 864 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) 865 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE 866 #endif 867 #if \ 868 defined(__has_cpp_attribute) && \ 869 defined(__cplusplus) && \ 870 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) 871 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) 872 #else 873 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) 874 #endif 875 876 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) 877 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS 878 #endif 879 #if !defined(__cplusplus) || !defined(__has_cpp_attribute) 880 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) 881 #elif \ 882 !defined(JSON_HEDLEY_PGI_VERSION) && \ 883 !defined(JSON_HEDLEY_IAR_VERSION) && \ 884 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ 885 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) 886 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) 887 #else 888 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) 889 #endif 890 891 #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) 892 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE 893 #endif 894 #if defined(__has_cpp_attribute) && defined(__cplusplus) 895 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) 896 #else 897 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 898 #endif 899 900 #if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) 901 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE 902 #endif 903 #if defined(__has_cpp_attribute) && defined(__cplusplus) 904 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) 905 #else 906 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 907 #endif 908 909 #if defined(JSON_HEDLEY_HAS_BUILTIN) 910 #undef JSON_HEDLEY_HAS_BUILTIN 911 #endif 912 #if defined(__has_builtin) 913 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) 914 #else 915 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) 916 #endif 917 918 #if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) 919 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN 920 #endif 921 #if defined(__has_builtin) 922 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) 923 #else 924 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 925 #endif 926 927 #if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) 928 #undef JSON_HEDLEY_GCC_HAS_BUILTIN 929 #endif 930 #if defined(__has_builtin) 931 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) 932 #else 933 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 934 #endif 935 936 #if defined(JSON_HEDLEY_HAS_FEATURE) 937 #undef JSON_HEDLEY_HAS_FEATURE 938 #endif 939 #if defined(__has_feature) 940 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) 941 #else 942 #define JSON_HEDLEY_HAS_FEATURE(feature) (0) 943 #endif 944 945 #if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) 946 #undef JSON_HEDLEY_GNUC_HAS_FEATURE 947 #endif 948 #if defined(__has_feature) 949 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) 950 #else 951 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 952 #endif 953 954 #if defined(JSON_HEDLEY_GCC_HAS_FEATURE) 955 #undef JSON_HEDLEY_GCC_HAS_FEATURE 956 #endif 957 #if defined(__has_feature) 958 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) 959 #else 960 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 961 #endif 962 963 #if defined(JSON_HEDLEY_HAS_EXTENSION) 964 #undef JSON_HEDLEY_HAS_EXTENSION 965 #endif 966 #if defined(__has_extension) 967 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) 968 #else 969 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) 970 #endif 971 972 #if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) 973 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION 974 #endif 975 #if defined(__has_extension) 976 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) 977 #else 978 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 979 #endif 980 981 #if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) 982 #undef JSON_HEDLEY_GCC_HAS_EXTENSION 983 #endif 984 #if defined(__has_extension) 985 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) 986 #else 987 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 988 #endif 989 990 #if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) 991 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE 992 #endif 993 #if defined(__has_declspec_attribute) 994 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) 995 #else 996 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) 997 #endif 998 999 #if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) 1000 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE 1001 #endif 1002 #if defined(__has_declspec_attribute) 1003 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) 1004 #else 1005 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 1006 #endif 1007 1008 #if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) 1009 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE 1010 #endif 1011 #if defined(__has_declspec_attribute) 1012 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) 1013 #else 1014 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 1015 #endif 1016 1017 #if defined(JSON_HEDLEY_HAS_WARNING) 1018 #undef JSON_HEDLEY_HAS_WARNING 1019 #endif 1020 #if defined(__has_warning) 1021 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) 1022 #else 1023 #define JSON_HEDLEY_HAS_WARNING(warning) (0) 1024 #endif 1025 1026 #if defined(JSON_HEDLEY_GNUC_HAS_WARNING) 1027 #undef JSON_HEDLEY_GNUC_HAS_WARNING 1028 #endif 1029 #if defined(__has_warning) 1030 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) 1031 #else 1032 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 1033 #endif 1034 1035 #if defined(JSON_HEDLEY_GCC_HAS_WARNING) 1036 #undef JSON_HEDLEY_GCC_HAS_WARNING 1037 #endif 1038 #if defined(__has_warning) 1039 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) 1040 #else 1041 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 1042 #endif 1043 1044 #if \ 1045 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ 1046 defined(__clang__) || \ 1047 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ 1048 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1049 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ 1050 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ 1051 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1052 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1053 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ 1054 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ 1055 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ 1056 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ 1057 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1058 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1059 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ 1060 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ 1061 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ 1062 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) 1063 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) 1064 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) 1065 #define JSON_HEDLEY_PRAGMA(value) __pragma(value) 1066 #else 1067 #define JSON_HEDLEY_PRAGMA(value) 1068 #endif 1069 1070 #if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) 1071 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH 1072 #endif 1073 #if defined(JSON_HEDLEY_DIAGNOSTIC_POP) 1074 #undef JSON_HEDLEY_DIAGNOSTIC_POP 1075 #endif 1076 #if defined(__clang__) 1077 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") 1078 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") 1079 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 1080 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") 1081 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") 1082 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) 1083 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") 1084 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") 1085 #elif \ 1086 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ 1087 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1088 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) 1089 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) 1090 #elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) 1091 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") 1092 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") 1093 #elif \ 1094 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1095 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1096 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ 1097 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ 1098 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1099 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) 1100 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") 1101 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") 1102 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) 1103 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") 1104 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") 1105 #else 1106 #define JSON_HEDLEY_DIAGNOSTIC_PUSH 1107 #define JSON_HEDLEY_DIAGNOSTIC_POP 1108 #endif 1109 1110 /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for 1111 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ 1112 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) 1113 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ 1114 #endif 1115 #if defined(__cplusplus) 1116 # if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") 1117 # if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") 1118 # if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") 1119 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ 1120 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1121 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ 1122 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ 1123 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ 1124 xpr \ 1125 JSON_HEDLEY_DIAGNOSTIC_POP 1126 # else 1127 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ 1128 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1129 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ 1130 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ 1131 xpr \ 1132 JSON_HEDLEY_DIAGNOSTIC_POP 1133 # endif 1134 # else 1135 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ 1136 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1137 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ 1138 xpr \ 1139 JSON_HEDLEY_DIAGNOSTIC_POP 1140 # endif 1141 # endif 1142 #endif 1143 #if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) 1144 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x 1145 #endif 1146 1147 #if defined(JSON_HEDLEY_CONST_CAST) 1148 #undef JSON_HEDLEY_CONST_CAST 1149 #endif 1150 #if defined(__cplusplus) 1151 # define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr)) 1152 #elif \ 1153 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ 1154 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ 1155 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 1156 # define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ 1157 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1158 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ 1159 ((T) (expr)); \ 1160 JSON_HEDLEY_DIAGNOSTIC_POP \ 1161 })) 1162 #else 1163 # define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) 1164 #endif 1165 1166 #if defined(JSON_HEDLEY_REINTERPRET_CAST) 1167 #undef JSON_HEDLEY_REINTERPRET_CAST 1168 #endif 1169 #if defined(__cplusplus) 1170 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr)) 1171 #else 1172 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) 1173 #endif 1174 1175 #if defined(JSON_HEDLEY_STATIC_CAST) 1176 #undef JSON_HEDLEY_STATIC_CAST 1177 #endif 1178 #if defined(__cplusplus) 1179 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr)) 1180 #else 1181 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) 1182 #endif 1183 1184 #if defined(JSON_HEDLEY_CPP_CAST) 1185 #undef JSON_HEDLEY_CPP_CAST 1186 #endif 1187 #if defined(__cplusplus) 1188 # if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") 1189 # define JSON_HEDLEY_CPP_CAST(T, expr) \ 1190 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1191 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ 1192 ((T) (expr)) \ 1193 JSON_HEDLEY_DIAGNOSTIC_POP 1194 # elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) 1195 # define JSON_HEDLEY_CPP_CAST(T, expr) \ 1196 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1197 _Pragma("diag_suppress=Pe137") \ 1198 JSON_HEDLEY_DIAGNOSTIC_POP 1199 # else 1200 # define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) 1201 # endif 1202 #else 1203 # define JSON_HEDLEY_CPP_CAST(T, expr) (expr) 1204 #endif 1205 1206 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) 1207 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED 1208 #endif 1209 #if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") 1210 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") 1211 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 1212 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") 1213 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1214 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) 1215 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) 1216 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") 1217 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) 1218 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") 1219 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) 1220 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") 1221 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) 1222 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) 1223 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1224 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") 1225 #elif \ 1226 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1227 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1228 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1229 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1230 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1231 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1232 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1233 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1234 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1235 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1236 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) 1237 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") 1238 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) 1239 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") 1240 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) 1241 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") 1242 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1243 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") 1244 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) 1245 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") 1246 #else 1247 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED 1248 #endif 1249 1250 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) 1251 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS 1252 #endif 1253 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") 1254 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") 1255 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 1256 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") 1257 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1258 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) 1259 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) 1260 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") 1261 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) 1262 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") 1263 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) 1264 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) 1265 #elif \ 1266 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ 1267 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ 1268 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1269 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) 1270 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") 1271 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) 1272 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") 1273 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1274 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") 1275 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1276 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") 1277 #else 1278 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS 1279 #endif 1280 1281 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) 1282 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES 1283 #endif 1284 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") 1285 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") 1286 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) 1287 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") 1288 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) 1289 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") 1290 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1291 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) 1292 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) 1293 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) 1294 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) 1295 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") 1296 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) 1297 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") 1298 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) 1299 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") 1300 #elif \ 1301 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ 1302 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ 1303 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) 1304 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") 1305 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1306 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") 1307 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1308 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") 1309 #else 1310 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES 1311 #endif 1312 1313 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) 1314 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL 1315 #endif 1316 #if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") 1317 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") 1318 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 1319 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") 1320 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) 1321 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") 1322 #else 1323 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL 1324 #endif 1325 1326 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) 1327 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION 1328 #endif 1329 #if JSON_HEDLEY_HAS_WARNING("-Wunused-function") 1330 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") 1331 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) 1332 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") 1333 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) 1334 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) 1335 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1336 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") 1337 #else 1338 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION 1339 #endif 1340 1341 #if defined(JSON_HEDLEY_DEPRECATED) 1342 #undef JSON_HEDLEY_DEPRECATED 1343 #endif 1344 #if defined(JSON_HEDLEY_DEPRECATED_FOR) 1345 #undef JSON_HEDLEY_DEPRECATED_FOR 1346 #endif 1347 #if \ 1348 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ 1349 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1350 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) 1351 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) 1352 #elif \ 1353 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ 1354 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ 1355 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1356 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ 1357 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ 1358 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 1359 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ 1360 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ 1361 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ 1362 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1363 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ 1364 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1365 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) 1366 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) 1367 #elif defined(__cplusplus) && (__cplusplus >= 201402L) 1368 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) 1369 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) 1370 #elif \ 1371 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ 1372 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ 1373 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1374 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1375 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1376 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1377 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1378 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1379 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1380 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1381 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1382 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1383 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1384 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1385 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ 1386 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) 1387 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) 1388 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) 1389 #elif \ 1390 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ 1391 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ 1392 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1393 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) 1394 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) 1395 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1396 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") 1397 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") 1398 #else 1399 #define JSON_HEDLEY_DEPRECATED(since) 1400 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) 1401 #endif 1402 1403 #if defined(JSON_HEDLEY_UNAVAILABLE) 1404 #undef JSON_HEDLEY_UNAVAILABLE 1405 #endif 1406 #if \ 1407 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ 1408 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ 1409 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1410 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1411 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) 1412 #else 1413 #define JSON_HEDLEY_UNAVAILABLE(available_since) 1414 #endif 1415 1416 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) 1417 #undef JSON_HEDLEY_WARN_UNUSED_RESULT 1418 #endif 1419 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) 1420 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG 1421 #endif 1422 #if \ 1423 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ 1424 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ 1425 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1426 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1427 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1428 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1429 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1430 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1431 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1432 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1433 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1434 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1435 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1436 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1437 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ 1438 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 1439 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1440 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) 1441 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) 1442 #elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) 1443 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) 1444 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) 1445 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) 1446 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) 1447 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) 1448 #elif defined(_Check_return_) /* SAL */ 1449 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ 1450 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ 1451 #else 1452 #define JSON_HEDLEY_WARN_UNUSED_RESULT 1453 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) 1454 #endif 1455 1456 #if defined(JSON_HEDLEY_SENTINEL) 1457 #undef JSON_HEDLEY_SENTINEL 1458 #endif 1459 #if \ 1460 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ 1461 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ 1462 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1463 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ 1464 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1465 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) 1466 #else 1467 #define JSON_HEDLEY_SENTINEL(position) 1468 #endif 1469 1470 #if defined(JSON_HEDLEY_NO_RETURN) 1471 #undef JSON_HEDLEY_NO_RETURN 1472 #endif 1473 #if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1474 #define JSON_HEDLEY_NO_RETURN __noreturn 1475 #elif \ 1476 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1477 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1478 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) 1479 #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L 1480 #define JSON_HEDLEY_NO_RETURN _Noreturn 1481 #elif defined(__cplusplus) && (__cplusplus >= 201103L) 1482 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) 1483 #elif \ 1484 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ 1485 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ 1486 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1487 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1488 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1489 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1490 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1491 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1492 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1493 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1494 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1495 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1496 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1497 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1498 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1499 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1500 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) 1501 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) 1502 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) 1503 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") 1504 #elif \ 1505 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ 1506 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1507 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) 1508 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) 1509 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") 1510 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) 1511 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) 1512 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) 1513 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) 1514 #else 1515 #define JSON_HEDLEY_NO_RETURN 1516 #endif 1517 1518 #if defined(JSON_HEDLEY_NO_ESCAPE) 1519 #undef JSON_HEDLEY_NO_ESCAPE 1520 #endif 1521 #if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) 1522 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) 1523 #else 1524 #define JSON_HEDLEY_NO_ESCAPE 1525 #endif 1526 1527 #if defined(JSON_HEDLEY_UNREACHABLE) 1528 #undef JSON_HEDLEY_UNREACHABLE 1529 #endif 1530 #if defined(JSON_HEDLEY_UNREACHABLE_RETURN) 1531 #undef JSON_HEDLEY_UNREACHABLE_RETURN 1532 #endif 1533 #if defined(JSON_HEDLEY_ASSUME) 1534 #undef JSON_HEDLEY_ASSUME 1535 #endif 1536 #if \ 1537 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ 1538 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1539 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1540 #define JSON_HEDLEY_ASSUME(expr) __assume(expr) 1541 #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) 1542 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) 1543 #elif \ 1544 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ 1545 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) 1546 #if defined(__cplusplus) 1547 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) 1548 #else 1549 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) 1550 #endif 1551 #endif 1552 #if \ 1553 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ 1554 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ 1555 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ 1556 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1557 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ 1558 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ 1559 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1560 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() 1561 #elif defined(JSON_HEDLEY_ASSUME) 1562 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) 1563 #endif 1564 #if !defined(JSON_HEDLEY_ASSUME) 1565 #if defined(JSON_HEDLEY_UNREACHABLE) 1566 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) 1567 #else 1568 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) 1569 #endif 1570 #endif 1571 #if defined(JSON_HEDLEY_UNREACHABLE) 1572 #if \ 1573 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ 1574 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) 1575 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) 1576 #else 1577 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() 1578 #endif 1579 #else 1580 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) 1581 #endif 1582 #if !defined(JSON_HEDLEY_UNREACHABLE) 1583 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) 1584 #endif 1585 1586 JSON_HEDLEY_DIAGNOSTIC_PUSH 1587 #if JSON_HEDLEY_HAS_WARNING("-Wpedantic") 1588 #pragma clang diagnostic ignored "-Wpedantic" 1589 #endif 1590 #if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) 1591 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" 1592 #endif 1593 #if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) 1594 #if defined(__clang__) 1595 #pragma clang diagnostic ignored "-Wvariadic-macros" 1596 #elif defined(JSON_HEDLEY_GCC_VERSION) 1597 #pragma GCC diagnostic ignored "-Wvariadic-macros" 1598 #endif 1599 #endif 1600 #if defined(JSON_HEDLEY_NON_NULL) 1601 #undef JSON_HEDLEY_NON_NULL 1602 #endif 1603 #if \ 1604 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ 1605 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ 1606 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1607 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) 1608 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) 1609 #else 1610 #define JSON_HEDLEY_NON_NULL(...) 1611 #endif 1612 JSON_HEDLEY_DIAGNOSTIC_POP 1613 1614 #if defined(JSON_HEDLEY_PRINTF_FORMAT) 1615 #undef JSON_HEDLEY_PRINTF_FORMAT 1616 #endif 1617 #if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) 1618 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) 1619 #elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) 1620 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) 1621 #elif \ 1622 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ 1623 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ 1624 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1625 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ 1626 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1627 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1628 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1629 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1630 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1631 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1632 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1633 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1634 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1635 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1636 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1637 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1638 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1639 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) 1640 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) 1641 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) 1642 #else 1643 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) 1644 #endif 1645 1646 #if defined(JSON_HEDLEY_CONSTEXPR) 1647 #undef JSON_HEDLEY_CONSTEXPR 1648 #endif 1649 #if defined(__cplusplus) 1650 #if __cplusplus >= 201103L 1651 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) 1652 #endif 1653 #endif 1654 #if !defined(JSON_HEDLEY_CONSTEXPR) 1655 #define JSON_HEDLEY_CONSTEXPR 1656 #endif 1657 1658 #if defined(JSON_HEDLEY_PREDICT) 1659 #undef JSON_HEDLEY_PREDICT 1660 #endif 1661 #if defined(JSON_HEDLEY_LIKELY) 1662 #undef JSON_HEDLEY_LIKELY 1663 #endif 1664 #if defined(JSON_HEDLEY_UNLIKELY) 1665 #undef JSON_HEDLEY_UNLIKELY 1666 #endif 1667 #if defined(JSON_HEDLEY_UNPREDICTABLE) 1668 #undef JSON_HEDLEY_UNPREDICTABLE 1669 #endif 1670 #if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) 1671 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) 1672 #endif 1673 #if \ 1674 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ 1675 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ 1676 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1677 # define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) 1678 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) 1679 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) 1680 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) 1681 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) 1682 #elif \ 1683 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ 1684 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ 1685 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1686 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ 1687 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1688 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1689 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1690 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ 1691 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ 1692 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ 1693 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ 1694 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1695 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1696 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ 1697 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ 1698 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1699 # define JSON_HEDLEY_PREDICT(expr, expected, probability) \ 1700 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) 1701 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ 1702 (__extension__ ({ \ 1703 double hedley_probability_ = (probability); \ 1704 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ 1705 })) 1706 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ 1707 (__extension__ ({ \ 1708 double hedley_probability_ = (probability); \ 1709 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ 1710 })) 1711 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) 1712 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) 1713 #else 1714 # define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) 1715 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) 1716 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) 1717 # define JSON_HEDLEY_LIKELY(expr) (!!(expr)) 1718 # define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) 1719 #endif 1720 #if !defined(JSON_HEDLEY_UNPREDICTABLE) 1721 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) 1722 #endif 1723 1724 #if defined(JSON_HEDLEY_MALLOC) 1725 #undef JSON_HEDLEY_MALLOC 1726 #endif 1727 #if \ 1728 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ 1729 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ 1730 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1731 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1732 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1733 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ 1734 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1735 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1736 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1737 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1738 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1739 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1740 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1741 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1742 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1743 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1744 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1745 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1746 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) 1747 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) 1748 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") 1749 #elif \ 1750 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ 1751 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1752 #define JSON_HEDLEY_MALLOC __declspec(restrict) 1753 #else 1754 #define JSON_HEDLEY_MALLOC 1755 #endif 1756 1757 #if defined(JSON_HEDLEY_PURE) 1758 #undef JSON_HEDLEY_PURE 1759 #endif 1760 #if \ 1761 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ 1762 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ 1763 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1764 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1765 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1766 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1767 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1768 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1769 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1770 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1771 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1772 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1773 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1774 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1775 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1776 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1777 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1778 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 1779 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1780 # define JSON_HEDLEY_PURE __attribute__((__pure__)) 1781 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) 1782 # define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") 1783 #elif defined(__cplusplus) && \ 1784 ( \ 1785 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ 1786 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ 1787 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ 1788 ) 1789 # define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") 1790 #else 1791 # define JSON_HEDLEY_PURE 1792 #endif 1793 1794 #if defined(JSON_HEDLEY_CONST) 1795 #undef JSON_HEDLEY_CONST 1796 #endif 1797 #if \ 1798 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ 1799 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ 1800 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1801 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1802 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1803 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1804 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1805 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1806 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1807 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1808 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1809 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1810 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1811 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1812 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1813 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1814 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1815 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 1816 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1817 #define JSON_HEDLEY_CONST __attribute__((__const__)) 1818 #elif \ 1819 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) 1820 #define JSON_HEDLEY_CONST _Pragma("no_side_effect") 1821 #else 1822 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE 1823 #endif 1824 1825 #if defined(JSON_HEDLEY_RESTRICT) 1826 #undef JSON_HEDLEY_RESTRICT 1827 #endif 1828 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) 1829 #define JSON_HEDLEY_RESTRICT restrict 1830 #elif \ 1831 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ 1832 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ 1833 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1834 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ 1835 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1836 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1837 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 1838 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1839 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ 1840 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ 1841 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1842 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ 1843 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ 1844 defined(__clang__) || \ 1845 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1846 #define JSON_HEDLEY_RESTRICT __restrict 1847 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) 1848 #define JSON_HEDLEY_RESTRICT _Restrict 1849 #else 1850 #define JSON_HEDLEY_RESTRICT 1851 #endif 1852 1853 #if defined(JSON_HEDLEY_INLINE) 1854 #undef JSON_HEDLEY_INLINE 1855 #endif 1856 #if \ 1857 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ 1858 (defined(__cplusplus) && (__cplusplus >= 199711L)) 1859 #define JSON_HEDLEY_INLINE inline 1860 #elif \ 1861 defined(JSON_HEDLEY_GCC_VERSION) || \ 1862 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) 1863 #define JSON_HEDLEY_INLINE __inline__ 1864 #elif \ 1865 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ 1866 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ 1867 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1868 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ 1869 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ 1870 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ 1871 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ 1872 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1873 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1874 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1875 #define JSON_HEDLEY_INLINE __inline 1876 #else 1877 #define JSON_HEDLEY_INLINE 1878 #endif 1879 1880 #if defined(JSON_HEDLEY_ALWAYS_INLINE) 1881 #undef JSON_HEDLEY_ALWAYS_INLINE 1882 #endif 1883 #if \ 1884 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ 1885 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ 1886 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1887 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1888 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1889 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1890 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1891 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1892 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1893 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1894 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1895 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1896 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1897 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1898 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1899 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1900 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1901 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ 1902 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) 1903 # define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE 1904 #elif \ 1905 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ 1906 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1907 # define JSON_HEDLEY_ALWAYS_INLINE __forceinline 1908 #elif defined(__cplusplus) && \ 1909 ( \ 1910 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1911 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1912 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1913 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ 1914 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1915 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ 1916 ) 1917 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") 1918 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1919 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") 1920 #else 1921 # define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE 1922 #endif 1923 1924 #if defined(JSON_HEDLEY_NEVER_INLINE) 1925 #undef JSON_HEDLEY_NEVER_INLINE 1926 #endif 1927 #if \ 1928 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ 1929 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ 1930 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1931 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1932 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1933 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1934 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1935 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1936 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1937 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1938 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1939 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1940 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1941 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1942 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1943 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1944 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1945 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ 1946 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) 1947 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) 1948 #elif \ 1949 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ 1950 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1951 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) 1952 #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) 1953 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") 1954 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) 1955 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") 1956 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1957 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") 1958 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) 1959 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) 1960 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) 1961 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) 1962 #else 1963 #define JSON_HEDLEY_NEVER_INLINE 1964 #endif 1965 1966 #if defined(JSON_HEDLEY_PRIVATE) 1967 #undef JSON_HEDLEY_PRIVATE 1968 #endif 1969 #if defined(JSON_HEDLEY_PUBLIC) 1970 #undef JSON_HEDLEY_PUBLIC 1971 #endif 1972 #if defined(JSON_HEDLEY_IMPORT) 1973 #undef JSON_HEDLEY_IMPORT 1974 #endif 1975 #if defined(_WIN32) || defined(__CYGWIN__) 1976 # define JSON_HEDLEY_PRIVATE 1977 # define JSON_HEDLEY_PUBLIC __declspec(dllexport) 1978 # define JSON_HEDLEY_IMPORT __declspec(dllimport) 1979 #else 1980 # if \ 1981 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ 1982 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ 1983 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1984 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1985 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1986 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ 1987 ( \ 1988 defined(__TI_EABI__) && \ 1989 ( \ 1990 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1991 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ 1992 ) \ 1993 ) || \ 1994 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1995 # define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) 1996 # define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) 1997 # else 1998 # define JSON_HEDLEY_PRIVATE 1999 # define JSON_HEDLEY_PUBLIC 2000 # endif 2001 # define JSON_HEDLEY_IMPORT extern 2002 #endif 2003 2004 #if defined(JSON_HEDLEY_NO_THROW) 2005 #undef JSON_HEDLEY_NO_THROW 2006 #endif 2007 #if \ 2008 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ 2009 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ 2010 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 2011 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 2012 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) 2013 #elif \ 2014 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ 2015 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ 2016 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) 2017 #define JSON_HEDLEY_NO_THROW __declspec(nothrow) 2018 #else 2019 #define JSON_HEDLEY_NO_THROW 2020 #endif 2021 2022 #if defined(JSON_HEDLEY_FALL_THROUGH) 2023 #undef JSON_HEDLEY_FALL_THROUGH 2024 #endif 2025 #if \ 2026 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ 2027 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ 2028 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 2029 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) 2030 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) 2031 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) 2032 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) 2033 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) 2034 #elif defined(__fallthrough) /* SAL */ 2035 #define JSON_HEDLEY_FALL_THROUGH __fallthrough 2036 #else 2037 #define JSON_HEDLEY_FALL_THROUGH 2038 #endif 2039 2040 #if defined(JSON_HEDLEY_RETURNS_NON_NULL) 2041 #undef JSON_HEDLEY_RETURNS_NON_NULL 2042 #endif 2043 #if \ 2044 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ 2045 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ 2046 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 2047 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) 2048 #elif defined(_Ret_notnull_) /* SAL */ 2049 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ 2050 #else 2051 #define JSON_HEDLEY_RETURNS_NON_NULL 2052 #endif 2053 2054 #if defined(JSON_HEDLEY_ARRAY_PARAM) 2055 #undef JSON_HEDLEY_ARRAY_PARAM 2056 #endif 2057 #if \ 2058 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ 2059 !defined(__STDC_NO_VLA__) && \ 2060 !defined(__cplusplus) && \ 2061 !defined(JSON_HEDLEY_PGI_VERSION) && \ 2062 !defined(JSON_HEDLEY_TINYC_VERSION) 2063 #define JSON_HEDLEY_ARRAY_PARAM(name) (name) 2064 #else 2065 #define JSON_HEDLEY_ARRAY_PARAM(name) 2066 #endif 2067 2068 #if defined(JSON_HEDLEY_IS_CONSTANT) 2069 #undef JSON_HEDLEY_IS_CONSTANT 2070 #endif 2071 #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) 2072 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR 2073 #endif 2074 /* JSON_HEDLEY_IS_CONSTEXPR_ is for 2075 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ 2076 #if defined(JSON_HEDLEY_IS_CONSTEXPR_) 2077 #undef JSON_HEDLEY_IS_CONSTEXPR_ 2078 #endif 2079 #if \ 2080 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ 2081 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ 2082 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 2083 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ 2084 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 2085 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ 2086 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ 2087 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ 2088 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ 2089 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 2090 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) 2091 #endif 2092 #if !defined(__cplusplus) 2093 # if \ 2094 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ 2095 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ 2096 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 2097 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ 2098 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ 2099 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ 2100 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) 2101 #if defined(__INTPTR_TYPE__) 2102 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) 2103 #else 2104 #include <stdint.h> 2105 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) 2106 #endif 2107 # elif \ 2108 ( \ 2109 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ 2110 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ 2111 !defined(JSON_HEDLEY_PGI_VERSION) && \ 2112 !defined(JSON_HEDLEY_IAR_VERSION)) || \ 2113 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ 2114 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ 2115 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ 2116 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ 2117 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) 2118 #if defined(__INTPTR_TYPE__) 2119 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) 2120 #else 2121 #include <stdint.h> 2122 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) 2123 #endif 2124 # elif \ 2125 defined(JSON_HEDLEY_GCC_VERSION) || \ 2126 defined(JSON_HEDLEY_INTEL_VERSION) || \ 2127 defined(JSON_HEDLEY_TINYC_VERSION) || \ 2128 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ 2129 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ 2130 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ 2131 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ 2132 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ 2133 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ 2134 defined(__clang__) 2135 # define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ 2136 sizeof(void) != \ 2137 sizeof(*( \ 2138 1 ? \ 2139 ((void*) ((expr) * 0L) ) : \ 2140 ((struct { char v[sizeof(void) * 2]; } *) 1) \ 2141 ) \ 2142 ) \ 2143 ) 2144 # endif 2145 #endif 2146 #if defined(JSON_HEDLEY_IS_CONSTEXPR_) 2147 #if !defined(JSON_HEDLEY_IS_CONSTANT) 2148 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) 2149 #endif 2150 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) 2151 #else 2152 #if !defined(JSON_HEDLEY_IS_CONSTANT) 2153 #define JSON_HEDLEY_IS_CONSTANT(expr) (0) 2154 #endif 2155 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) 2156 #endif 2157 2158 #if defined(JSON_HEDLEY_BEGIN_C_DECLS) 2159 #undef JSON_HEDLEY_BEGIN_C_DECLS 2160 #endif 2161 #if defined(JSON_HEDLEY_END_C_DECLS) 2162 #undef JSON_HEDLEY_END_C_DECLS 2163 #endif 2164 #if defined(JSON_HEDLEY_C_DECL) 2165 #undef JSON_HEDLEY_C_DECL 2166 #endif 2167 #if defined(__cplusplus) 2168 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { 2169 #define JSON_HEDLEY_END_C_DECLS } 2170 #define JSON_HEDLEY_C_DECL extern "C" 2171 #else 2172 #define JSON_HEDLEY_BEGIN_C_DECLS 2173 #define JSON_HEDLEY_END_C_DECLS 2174 #define JSON_HEDLEY_C_DECL 2175 #endif 2176 2177 #if defined(JSON_HEDLEY_STATIC_ASSERT) 2178 #undef JSON_HEDLEY_STATIC_ASSERT 2179 #endif 2180 #if \ 2181 !defined(__cplusplus) && ( \ 2182 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ 2183 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ 2184 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ 2185 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 2186 defined(_Static_assert) \ 2187 ) 2188 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) 2189 #elif \ 2190 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ 2191 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ 2192 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 2193 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) 2194 #else 2195 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) 2196 #endif 2197 2198 #if defined(JSON_HEDLEY_NULL) 2199 #undef JSON_HEDLEY_NULL 2200 #endif 2201 #if defined(__cplusplus) 2202 #if __cplusplus >= 201103L 2203 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) 2204 #elif defined(NULL) 2205 #define JSON_HEDLEY_NULL NULL 2206 #else 2207 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) 2208 #endif 2209 #elif defined(NULL) 2210 #define JSON_HEDLEY_NULL NULL 2211 #else 2212 #define JSON_HEDLEY_NULL ((void*) 0) 2213 #endif 2214 2215 #if defined(JSON_HEDLEY_MESSAGE) 2216 #undef JSON_HEDLEY_MESSAGE 2217 #endif 2218 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") 2219 # define JSON_HEDLEY_MESSAGE(msg) \ 2220 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2221 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ 2222 JSON_HEDLEY_PRAGMA(message msg) \ 2223 JSON_HEDLEY_DIAGNOSTIC_POP 2224 #elif \ 2225 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ 2226 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 2227 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) 2228 #elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) 2229 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) 2230 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 2231 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) 2232 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) 2233 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) 2234 #else 2235 # define JSON_HEDLEY_MESSAGE(msg) 2236 #endif 2237 2238 #if defined(JSON_HEDLEY_WARNING) 2239 #undef JSON_HEDLEY_WARNING 2240 #endif 2241 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") 2242 # define JSON_HEDLEY_WARNING(msg) \ 2243 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2244 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ 2245 JSON_HEDLEY_PRAGMA(clang warning msg) \ 2246 JSON_HEDLEY_DIAGNOSTIC_POP 2247 #elif \ 2248 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ 2249 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ 2250 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 2251 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) 2252 #elif \ 2253 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ 2254 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 2255 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) 2256 #else 2257 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) 2258 #endif 2259 2260 #if defined(JSON_HEDLEY_REQUIRE) 2261 #undef JSON_HEDLEY_REQUIRE 2262 #endif 2263 #if defined(JSON_HEDLEY_REQUIRE_MSG) 2264 #undef JSON_HEDLEY_REQUIRE_MSG 2265 #endif 2266 #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) 2267 # if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") 2268 # define JSON_HEDLEY_REQUIRE(expr) \ 2269 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2270 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ 2271 __attribute__((diagnose_if(!(expr), #expr, "error"))) \ 2272 JSON_HEDLEY_DIAGNOSTIC_POP 2273 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ 2274 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2275 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ 2276 __attribute__((diagnose_if(!(expr), msg, "error"))) \ 2277 JSON_HEDLEY_DIAGNOSTIC_POP 2278 # else 2279 # define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) 2280 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) 2281 # endif 2282 #else 2283 # define JSON_HEDLEY_REQUIRE(expr) 2284 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) 2285 #endif 2286 2287 #if defined(JSON_HEDLEY_FLAGS) 2288 #undef JSON_HEDLEY_FLAGS 2289 #endif 2290 #if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) 2291 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) 2292 #else 2293 #define JSON_HEDLEY_FLAGS 2294 #endif 2295 2296 #if defined(JSON_HEDLEY_FLAGS_CAST) 2297 #undef JSON_HEDLEY_FLAGS_CAST 2298 #endif 2299 #if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) 2300 # define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ 2301 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2302 _Pragma("warning(disable:188)") \ 2303 ((T) (expr)); \ 2304 JSON_HEDLEY_DIAGNOSTIC_POP \ 2305 })) 2306 #else 2307 # define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) 2308 #endif 2309 2310 #if defined(JSON_HEDLEY_EMPTY_BASES) 2311 #undef JSON_HEDLEY_EMPTY_BASES 2312 #endif 2313 #if \ 2314 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ 2315 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 2316 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) 2317 #else 2318 #define JSON_HEDLEY_EMPTY_BASES 2319 #endif 2320 2321 /* Remaining macros are deprecated. */ 2322 2323 #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) 2324 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK 2325 #endif 2326 #if defined(__clang__) 2327 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) 2328 #else 2329 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 2330 #endif 2331 2332 #if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) 2333 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE 2334 #endif 2335 #define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) 2336 2337 #if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) 2338 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE 2339 #endif 2340 #define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) 2341 2342 #if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) 2343 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN 2344 #endif 2345 #define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) 2346 2347 #if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) 2348 #undef JSON_HEDLEY_CLANG_HAS_FEATURE 2349 #endif 2350 #define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) 2351 2352 #if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) 2353 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION 2354 #endif 2355 #define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) 2356 2357 #if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) 2358 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE 2359 #endif 2360 #define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) 2361 2362 #if defined(JSON_HEDLEY_CLANG_HAS_WARNING) 2363 #undef JSON_HEDLEY_CLANG_HAS_WARNING 2364 #endif 2365 #define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) 2366 2367 #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ 2368 2369 2370 // This file contains all internal macro definitions (except those affecting ABI) 2371 // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them 2372 2373 // #include <nlohmann/detail/abi_macros.hpp> 2374 2375 2376 // exclude unsupported compilers 2377 #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) 2378 #if defined(__clang__) 2379 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 2380 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" 2381 #endif 2382 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) 2383 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 2384 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" 2385 #endif 2386 #endif 2387 #endif 2388 2389 // C++ language standard detection 2390 // if the user manually specified the used c++ version this is skipped 2391 #if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) 2392 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) 2393 #define JSON_HAS_CPP_20 2394 #define JSON_HAS_CPP_17 2395 #define JSON_HAS_CPP_14 2396 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 2397 #define JSON_HAS_CPP_17 2398 #define JSON_HAS_CPP_14 2399 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) 2400 #define JSON_HAS_CPP_14 2401 #endif 2402 // the cpp 11 flag is always specified because it is the minimal required version 2403 #define JSON_HAS_CPP_11 2404 #endif 2405 2406 #ifdef __has_include 2407 #if __has_include(<version>) 2408 #include <version> 2409 #endif 2410 #endif 2411 2412 #if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) 2413 #ifdef JSON_HAS_CPP_17 2414 #if defined(__cpp_lib_filesystem) 2415 #define JSON_HAS_FILESYSTEM 1 2416 #elif defined(__cpp_lib_experimental_filesystem) 2417 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 2418 #elif !defined(__has_include) 2419 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 2420 #elif __has_include(<filesystem>) 2421 #define JSON_HAS_FILESYSTEM 1 2422 #elif __has_include(<experimental/filesystem>) 2423 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 2424 #endif 2425 2426 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ 2427 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 2428 #undef JSON_HAS_FILESYSTEM 2429 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2430 #endif 2431 2432 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support 2433 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 2434 #undef JSON_HAS_FILESYSTEM 2435 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2436 #endif 2437 2438 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support 2439 #if defined(__clang_major__) && __clang_major__ < 7 2440 #undef JSON_HAS_FILESYSTEM 2441 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2442 #endif 2443 2444 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support 2445 #if defined(_MSC_VER) && _MSC_VER < 1914 2446 #undef JSON_HAS_FILESYSTEM 2447 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2448 #endif 2449 2450 // no filesystem support before iOS 13 2451 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 2452 #undef JSON_HAS_FILESYSTEM 2453 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2454 #endif 2455 2456 // no filesystem support before macOS Catalina 2457 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 2458 #undef JSON_HAS_FILESYSTEM 2459 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2460 #endif 2461 #endif 2462 #endif 2463 2464 #ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2465 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 2466 #endif 2467 2468 #ifndef JSON_HAS_FILESYSTEM 2469 #define JSON_HAS_FILESYSTEM 0 2470 #endif 2471 2472 #ifndef JSON_HAS_THREE_WAY_COMPARISON 2473 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ 2474 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L 2475 #define JSON_HAS_THREE_WAY_COMPARISON 1 2476 #else 2477 #define JSON_HAS_THREE_WAY_COMPARISON 0 2478 #endif 2479 #endif 2480 2481 #ifndef JSON_HAS_RANGES 2482 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error 2483 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 2484 #define JSON_HAS_RANGES 0 2485 #elif defined(__cpp_lib_ranges) 2486 #define JSON_HAS_RANGES 1 2487 #else 2488 #define JSON_HAS_RANGES 0 2489 #endif 2490 #endif 2491 2492 #ifndef JSON_HAS_STATIC_RTTI 2493 #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 2494 #define JSON_HAS_STATIC_RTTI 1 2495 #else 2496 #define JSON_HAS_STATIC_RTTI 0 2497 #endif 2498 #endif 2499 2500 #ifdef JSON_HAS_CPP_17 2501 #define JSON_INLINE_VARIABLE inline 2502 #else 2503 #define JSON_INLINE_VARIABLE 2504 #endif 2505 2506 #if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) 2507 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] 2508 #else 2509 #define JSON_NO_UNIQUE_ADDRESS 2510 #endif 2511 2512 // disable documentation warnings on clang 2513 #if defined(__clang__) 2514 #pragma clang diagnostic push 2515 #pragma clang diagnostic ignored "-Wdocumentation" 2516 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" 2517 #endif 2518 2519 // allow disabling exceptions 2520 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) 2521 #define JSON_THROW(exception) throw exception 2522 #define JSON_TRY try 2523 #define JSON_CATCH(exception) catch(exception) 2524 #define JSON_INTERNAL_CATCH(exception) catch(exception) 2525 #else 2526 #include <cstdlib> 2527 #define JSON_THROW(exception) std::abort() 2528 #define JSON_TRY if(true) 2529 #define JSON_CATCH(exception) if(false) 2530 #define JSON_INTERNAL_CATCH(exception) if(false) 2531 #endif 2532 2533 // override exception macros 2534 #if defined(JSON_THROW_USER) 2535 #undef JSON_THROW 2536 #define JSON_THROW JSON_THROW_USER 2537 #endif 2538 #if defined(JSON_TRY_USER) 2539 #undef JSON_TRY 2540 #define JSON_TRY JSON_TRY_USER 2541 #endif 2542 #if defined(JSON_CATCH_USER) 2543 #undef JSON_CATCH 2544 #define JSON_CATCH JSON_CATCH_USER 2545 #undef JSON_INTERNAL_CATCH 2546 #define JSON_INTERNAL_CATCH JSON_CATCH_USER 2547 #endif 2548 #if defined(JSON_INTERNAL_CATCH_USER) 2549 #undef JSON_INTERNAL_CATCH 2550 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER 2551 #endif 2552 2553 // allow overriding assert 2554 #if !defined(JSON_ASSERT) 2555 #include <cassert> // assert 2556 #define JSON_ASSERT(x) assert(x) 2557 #endif 2558 2559 // allow to access some private functions (needed by the test suite) 2560 #if defined(JSON_TESTS_PRIVATE) 2561 #define JSON_PRIVATE_UNLESS_TESTED public 2562 #else 2563 #define JSON_PRIVATE_UNLESS_TESTED private 2564 #endif 2565 2566 /*! 2567 @brief macro to briefly define a mapping between an enum and JSON 2568 @def NLOHMANN_JSON_SERIALIZE_ENUM 2569 @since version 3.4.0 2570 */ 2571 #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ 2572 template<typename BasicJsonType> \ 2573 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ 2574 { \ 2575 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ 2576 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \ 2577 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \ 2578 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \ 2579 auto it = std::find_if(std::begin(m), std::end(m), \ 2580 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \ 2581 { \ 2582 return ej_pair.first == e; \ 2583 }); \ 2584 j = ((it != std::end(m)) ? it : std::begin(m))->second; \ 2585 } \ 2586 template<typename BasicJsonType> \ 2587 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ 2588 { \ 2589 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ 2590 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \ 2591 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \ 2592 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \ 2593 auto it = std::find_if(std::begin(m), std::end(m), \ 2594 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \ 2595 { \ 2596 return ej_pair.second == j; \ 2597 }); \ 2598 e = ((it != std::end(m)) ? it : std::begin(m))->first; \ 2599 } 2600 2601 // Ugly macros to avoid uglier copy-paste when specializing basic_json. They 2602 // may be removed in the future once the class is split. 2603 2604 #define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ 2605 template<template<typename, typename, typename...> class ObjectType, \ 2606 template<typename, typename...> class ArrayType, \ 2607 class StringType, class BooleanType, class NumberIntegerType, \ 2608 class NumberUnsignedType, class NumberFloatType, \ 2609 template<typename> class AllocatorType, \ 2610 template<typename, typename = void> class JSONSerializer, \ 2611 class BinaryType, \ 2612 class CustomBaseClass> 2613 2614 #define NLOHMANN_BASIC_JSON_TPL \ 2615 basic_json<ObjectType, ArrayType, StringType, BooleanType, \ 2616 NumberIntegerType, NumberUnsignedType, NumberFloatType, \ 2617 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass> 2618 2619 // Macros to simplify conversion from/to types 2620 2621 #define NLOHMANN_JSON_EXPAND( x ) x 2622 #define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME 2623 #define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ 2624 NLOHMANN_JSON_PASTE64, \ 2625 NLOHMANN_JSON_PASTE63, \ 2626 NLOHMANN_JSON_PASTE62, \ 2627 NLOHMANN_JSON_PASTE61, \ 2628 NLOHMANN_JSON_PASTE60, \ 2629 NLOHMANN_JSON_PASTE59, \ 2630 NLOHMANN_JSON_PASTE58, \ 2631 NLOHMANN_JSON_PASTE57, \ 2632 NLOHMANN_JSON_PASTE56, \ 2633 NLOHMANN_JSON_PASTE55, \ 2634 NLOHMANN_JSON_PASTE54, \ 2635 NLOHMANN_JSON_PASTE53, \ 2636 NLOHMANN_JSON_PASTE52, \ 2637 NLOHMANN_JSON_PASTE51, \ 2638 NLOHMANN_JSON_PASTE50, \ 2639 NLOHMANN_JSON_PASTE49, \ 2640 NLOHMANN_JSON_PASTE48, \ 2641 NLOHMANN_JSON_PASTE47, \ 2642 NLOHMANN_JSON_PASTE46, \ 2643 NLOHMANN_JSON_PASTE45, \ 2644 NLOHMANN_JSON_PASTE44, \ 2645 NLOHMANN_JSON_PASTE43, \ 2646 NLOHMANN_JSON_PASTE42, \ 2647 NLOHMANN_JSON_PASTE41, \ 2648 NLOHMANN_JSON_PASTE40, \ 2649 NLOHMANN_JSON_PASTE39, \ 2650 NLOHMANN_JSON_PASTE38, \ 2651 NLOHMANN_JSON_PASTE37, \ 2652 NLOHMANN_JSON_PASTE36, \ 2653 NLOHMANN_JSON_PASTE35, \ 2654 NLOHMANN_JSON_PASTE34, \ 2655 NLOHMANN_JSON_PASTE33, \ 2656 NLOHMANN_JSON_PASTE32, \ 2657 NLOHMANN_JSON_PASTE31, \ 2658 NLOHMANN_JSON_PASTE30, \ 2659 NLOHMANN_JSON_PASTE29, \ 2660 NLOHMANN_JSON_PASTE28, \ 2661 NLOHMANN_JSON_PASTE27, \ 2662 NLOHMANN_JSON_PASTE26, \ 2663 NLOHMANN_JSON_PASTE25, \ 2664 NLOHMANN_JSON_PASTE24, \ 2665 NLOHMANN_JSON_PASTE23, \ 2666 NLOHMANN_JSON_PASTE22, \ 2667 NLOHMANN_JSON_PASTE21, \ 2668 NLOHMANN_JSON_PASTE20, \ 2669 NLOHMANN_JSON_PASTE19, \ 2670 NLOHMANN_JSON_PASTE18, \ 2671 NLOHMANN_JSON_PASTE17, \ 2672 NLOHMANN_JSON_PASTE16, \ 2673 NLOHMANN_JSON_PASTE15, \ 2674 NLOHMANN_JSON_PASTE14, \ 2675 NLOHMANN_JSON_PASTE13, \ 2676 NLOHMANN_JSON_PASTE12, \ 2677 NLOHMANN_JSON_PASTE11, \ 2678 NLOHMANN_JSON_PASTE10, \ 2679 NLOHMANN_JSON_PASTE9, \ 2680 NLOHMANN_JSON_PASTE8, \ 2681 NLOHMANN_JSON_PASTE7, \ 2682 NLOHMANN_JSON_PASTE6, \ 2683 NLOHMANN_JSON_PASTE5, \ 2684 NLOHMANN_JSON_PASTE4, \ 2685 NLOHMANN_JSON_PASTE3, \ 2686 NLOHMANN_JSON_PASTE2, \ 2687 NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) 2688 #define NLOHMANN_JSON_PASTE2(func, v1) func(v1) 2689 #define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) 2690 #define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) 2691 #define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) 2692 #define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) 2693 #define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) 2694 #define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) 2695 #define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) 2696 #define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) 2697 #define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) 2698 #define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) 2699 #define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) 2700 #define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) 2701 #define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) 2702 #define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) 2703 #define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) 2704 #define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) 2705 #define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) 2706 #define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) 2707 #define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) 2708 #define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) 2709 #define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) 2710 #define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) 2711 #define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) 2712 #define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) 2713 #define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) 2714 #define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) 2715 #define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) 2716 #define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) 2717 #define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) 2718 #define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) 2719 #define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) 2720 #define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) 2721 #define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) 2722 #define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) 2723 #define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) 2724 #define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) 2725 #define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) 2726 #define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) 2727 #define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) 2728 #define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) 2729 #define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) 2730 #define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) 2731 #define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) 2732 #define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) 2733 #define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) 2734 #define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) 2735 #define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) 2736 #define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) 2737 #define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) 2738 #define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) 2739 #define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) 2740 #define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) 2741 #define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) 2742 #define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) 2743 #define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) 2744 #define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) 2745 #define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) 2746 #define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) 2747 #define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) 2748 #define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) 2749 #define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) 2750 #define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) 2751 2752 #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; 2753 #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); 2754 #define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); 2755 2756 /*! 2757 @brief macro 2758 @def NLOHMANN_DEFINE_TYPE_INTRUSIVE 2759 @since version 3.9.0 2760 */ 2761 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ 2762 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2763 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } 2764 2765 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ 2766 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2767 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } 2768 2769 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ 2770 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } 2771 2772 /*! 2773 @brief macro 2774 @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE 2775 @since version 3.9.0 2776 */ 2777 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ 2778 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2779 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } 2780 2781 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ 2782 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } 2783 2784 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ 2785 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2786 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } 2787 2788 /*! 2789 @brief macro 2790 @def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE 2791 @since version 3.11.x 2792 */ 2793 #define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \ 2794 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2795 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } 2796 2797 #define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ 2798 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2799 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } 2800 2801 /*! 2802 @brief macro 2803 @def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE 2804 @since version 3.11.x 2805 */ 2806 #define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \ 2807 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2808 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } 2809 2810 #define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ 2811 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ 2812 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } 2813 2814 // inspired from https://stackoverflow.com/a/26745591 2815 // allows to call any std function as if (e.g. with begin): 2816 // using std::begin; begin(x); 2817 // 2818 // it allows using the detected idiom to retrieve the return type 2819 // of such an expression 2820 #define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ 2821 namespace detail { \ 2822 using std::std_name; \ 2823 \ 2824 template<typename... T> \ 2825 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \ 2826 } \ 2827 \ 2828 namespace detail2 { \ 2829 struct std_name##_tag \ 2830 { \ 2831 }; \ 2832 \ 2833 template<typename... T> \ 2834 std_name##_tag std_name(T&&...); \ 2835 \ 2836 template<typename... T> \ 2837 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \ 2838 \ 2839 template<typename... T> \ 2840 struct would_call_std_##std_name \ 2841 { \ 2842 static constexpr auto const value = ::nlohmann::detail:: \ 2843 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \ 2844 }; \ 2845 } /* namespace detail2 */ \ 2846 \ 2847 template<typename... T> \ 2848 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \ 2849 { \ 2850 } 2851 2852 #ifndef JSON_USE_IMPLICIT_CONVERSIONS 2853 #define JSON_USE_IMPLICIT_CONVERSIONS 1 2854 #endif 2855 2856 #if JSON_USE_IMPLICIT_CONVERSIONS 2857 #define JSON_EXPLICIT 2858 #else 2859 #define JSON_EXPLICIT explicit 2860 #endif 2861 2862 #ifndef JSON_DISABLE_ENUM_SERIALIZATION 2863 #define JSON_DISABLE_ENUM_SERIALIZATION 0 2864 #endif 2865 2866 #ifndef JSON_USE_GLOBAL_UDLS 2867 #define JSON_USE_GLOBAL_UDLS 1 2868 #endif 2869 2870 #if JSON_HAS_THREE_WAY_COMPARISON 2871 #include <compare> // partial_ordering 2872 #endif 2873 2874 NLOHMANN_JSON_NAMESPACE_BEGIN 2875 namespace detail 2876 { 2877 2878 /////////////////////////// 2879 // JSON type enumeration // 2880 /////////////////////////// 2881 2882 /*! 2883 @brief the JSON type enumeration 2884 2885 This enumeration collects the different JSON types. It is internally used to 2886 distinguish the stored values, and the functions @ref basic_json::is_null(), 2887 @ref basic_json::is_object(), @ref basic_json::is_array(), 2888 @ref basic_json::is_string(), @ref basic_json::is_boolean(), 2889 @ref basic_json::is_number() (with @ref basic_json::is_number_integer(), 2890 @ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), 2891 @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and 2892 @ref basic_json::is_structured() rely on it. 2893 2894 @note There are three enumeration entries (number_integer, number_unsigned, and 2895 number_float), because the library distinguishes these three types for numbers: 2896 @ref basic_json::number_unsigned_t is used for unsigned integers, 2897 @ref basic_json::number_integer_t is used for signed integers, and 2898 @ref basic_json::number_float_t is used for floating-point numbers or to 2899 approximate integers which do not fit in the limits of their respective type. 2900 2901 @sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON 2902 value with the default value for a given type 2903 2904 @since version 1.0.0 2905 */ 2906 enum class value_t : std::uint8_t 2907 { 2908 null, ///< null value 2909 object, ///< object (unordered set of name/value pairs) 2910 array, ///< array (ordered collection of values) 2911 string, ///< string value 2912 boolean, ///< boolean value 2913 number_integer, ///< number value (signed integer) 2914 number_unsigned, ///< number value (unsigned integer) 2915 number_float, ///< number value (floating-point) 2916 binary, ///< binary array (ordered collection of bytes) 2917 discarded ///< discarded by the parser callback function 2918 }; 2919 2920 /*! 2921 @brief comparison operator for JSON types 2922 2923 Returns an ordering that is similar to Python: 2924 - order: null < boolean < number < object < array < string < binary 2925 - furthermore, each type is not smaller than itself 2926 - discarded values are not comparable 2927 - binary is represented as a b"" string in python and directly comparable to a 2928 string; however, making a binary array directly comparable with a string would 2929 be surprising behavior in a JSON file. 2930 2931 @since version 1.0.0 2932 */ 2933 #if JSON_HAS_THREE_WAY_COMPARISON 2934 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* 2935 #else 2936 inline bool operator<(const value_t lhs, const value_t rhs) noexcept 2937 #endif 2938 { 2939 static constexpr std::array<std::uint8_t, 9> order = {{ 2940 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, 2941 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, 2942 6 /* binary */ 2943 } 2944 }; 2945 2946 const auto l_index = static_cast<std::size_t>(lhs); 2947 const auto r_index = static_cast<std::size_t>(rhs); 2948 #if JSON_HAS_THREE_WAY_COMPARISON 2949 if (l_index < order.size() && r_index < order.size()) 2950 { 2951 return order[l_index] <=> order[r_index]; // *NOPAD* 2952 } 2953 return std::partial_ordering::unordered; 2954 #else 2955 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; 2956 #endif 2957 } 2958 2959 // GCC selects the built-in operator< over an operator rewritten from 2960 // a user-defined spaceship operator 2961 // Clang, MSVC, and ICC select the rewritten candidate 2962 // (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) 2963 #if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) 2964 inline bool operator<(const value_t lhs, const value_t rhs) noexcept 2965 { 2966 return std::is_lt(lhs <=> rhs); // *NOPAD* 2967 } 2968 #endif 2969 2970 } // namespace detail 2971 NLOHMANN_JSON_NAMESPACE_END 2972 2973 // #include <nlohmann/detail/string_escape.hpp> 2974 // __ _____ _____ _____ 2975 // __| | __| | | | JSON for Modern C++ 2976 // | | |__ | | | | | | version 3.11.3 2977 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 2978 // 2979 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 2980 // SPDX-License-Identifier: MIT 2981 2982 2983 2984 // #include <nlohmann/detail/abi_macros.hpp> 2985 2986 2987 NLOHMANN_JSON_NAMESPACE_BEGIN 2988 namespace detail 2989 { 2990 2991 /*! 2992 @brief replace all occurrences of a substring by another string 2993 2994 @param[in,out] s the string to manipulate; changed so that all 2995 occurrences of @a f are replaced with @a t 2996 @param[in] f the substring to replace with @a t 2997 @param[in] t the string to replace @a f 2998 2999 @pre The search string @a f must not be empty. **This precondition is 3000 enforced with an assertion.** 3001 3002 @since version 2.0.0 3003 */ 3004 template<typename StringType> 3005 inline void replace_substring(StringType& s, const StringType& f, 3006 const StringType& t) 3007 { 3008 JSON_ASSERT(!f.empty()); 3009 for (auto pos = s.find(f); // find first occurrence of f 3010 pos != StringType::npos; // make sure f was found 3011 s.replace(pos, f.size(), t), // replace with t, and 3012 pos = s.find(f, pos + t.size())) // find next occurrence of f 3013 {} 3014 } 3015 3016 /*! 3017 * @brief string escaping as described in RFC 6901 (Sect. 4) 3018 * @param[in] s string to escape 3019 * @return escaped string 3020 * 3021 * Note the order of escaping "~" to "~0" and "/" to "~1" is important. 3022 */ 3023 template<typename StringType> 3024 inline StringType escape(StringType s) 3025 { 3026 replace_substring(s, StringType{"~"}, StringType{"~0"}); 3027 replace_substring(s, StringType{"/"}, StringType{"~1"}); 3028 return s; 3029 } 3030 3031 /*! 3032 * @brief string unescaping as described in RFC 6901 (Sect. 4) 3033 * @param[in] s string to unescape 3034 * @return unescaped string 3035 * 3036 * Note the order of escaping "~1" to "/" and "~0" to "~" is important. 3037 */ 3038 template<typename StringType> 3039 static void unescape(StringType& s) 3040 { 3041 replace_substring(s, StringType{"~1"}, StringType{"/"}); 3042 replace_substring(s, StringType{"~0"}, StringType{"~"}); 3043 } 3044 3045 } // namespace detail 3046 NLOHMANN_JSON_NAMESPACE_END 3047 3048 // #include <nlohmann/detail/input/position_t.hpp> 3049 // __ _____ _____ _____ 3050 // __| | __| | | | JSON for Modern C++ 3051 // | | |__ | | | | | | version 3.11.3 3052 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3053 // 3054 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 3055 // SPDX-License-Identifier: MIT 3056 3057 3058 3059 #include <cstddef> // size_t 3060 3061 // #include <nlohmann/detail/abi_macros.hpp> 3062 3063 3064 NLOHMANN_JSON_NAMESPACE_BEGIN 3065 namespace detail 3066 { 3067 3068 /// struct to capture the start position of the current token 3069 struct position_t 3070 { 3071 /// the total number of characters read 3072 std::size_t chars_read_total = 0; 3073 /// the number of characters read in the current line 3074 std::size_t chars_read_current_line = 0; 3075 /// the number of lines read 3076 std::size_t lines_read = 0; 3077 3078 /// conversion to size_t to preserve SAX interface 3079 constexpr operator size_t() const 3080 { 3081 return chars_read_total; 3082 } 3083 }; 3084 3085 } // namespace detail 3086 NLOHMANN_JSON_NAMESPACE_END 3087 3088 // #include <nlohmann/detail/macro_scope.hpp> 3089 3090 // #include <nlohmann/detail/meta/cpp_future.hpp> 3091 // __ _____ _____ _____ 3092 // __| | __| | | | JSON for Modern C++ 3093 // | | |__ | | | | | | version 3.11.3 3094 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3095 // 3096 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 3097 // SPDX-FileCopyrightText: 2018 The Abseil Authors 3098 // SPDX-License-Identifier: MIT 3099 3100 3101 3102 #include <array> // array 3103 #include <cstddef> // size_t 3104 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type 3105 #include <utility> // index_sequence, make_index_sequence, index_sequence_for 3106 3107 // #include <nlohmann/detail/macro_scope.hpp> 3108 3109 3110 NLOHMANN_JSON_NAMESPACE_BEGIN 3111 namespace detail 3112 { 3113 3114 template<typename T> 3115 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type; 3116 3117 #ifdef JSON_HAS_CPP_14 3118 3119 // the following utilities are natively available in C++14 3120 using std::enable_if_t; 3121 using std::index_sequence; 3122 using std::make_index_sequence; 3123 using std::index_sequence_for; 3124 3125 #else 3126 3127 // alias templates to reduce boilerplate 3128 template<bool B, typename T = void> 3129 using enable_if_t = typename std::enable_if<B, T>::type; 3130 3131 // The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h 3132 // which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. 3133 3134 //// START OF CODE FROM GOOGLE ABSEIL 3135 3136 // integer_sequence 3137 // 3138 // Class template representing a compile-time integer sequence. An instantiation 3139 // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its 3140 // type through its template arguments (which is a common need when 3141 // working with C++11 variadic templates). `absl::integer_sequence` is designed 3142 // to be a drop-in replacement for C++14's `std::integer_sequence`. 3143 // 3144 // Example: 3145 // 3146 // template< class T, T... Ints > 3147 // void user_function(integer_sequence<T, Ints...>); 3148 // 3149 // int main() 3150 // { 3151 // // user_function's `T` will be deduced to `int` and `Ints...` 3152 // // will be deduced to `0, 1, 2, 3, 4`. 3153 // user_function(make_integer_sequence<int, 5>()); 3154 // } 3155 template <typename T, T... Ints> 3156 struct integer_sequence 3157 { 3158 using value_type = T; 3159 static constexpr std::size_t size() noexcept 3160 { 3161 return sizeof...(Ints); 3162 } 3163 }; 3164 3165 // index_sequence 3166 // 3167 // A helper template for an `integer_sequence` of `size_t`, 3168 // `absl::index_sequence` is designed to be a drop-in replacement for C++14's 3169 // `std::index_sequence`. 3170 template <size_t... Ints> 3171 using index_sequence = integer_sequence<size_t, Ints...>; 3172 3173 namespace utility_internal 3174 { 3175 3176 template <typename Seq, size_t SeqSize, size_t Rem> 3177 struct Extend; 3178 3179 // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. 3180 template <typename T, T... Ints, size_t SeqSize> 3181 struct Extend<integer_sequence<T, Ints...>, SeqSize, 0> 3182 { 3183 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; 3184 }; 3185 3186 template <typename T, T... Ints, size_t SeqSize> 3187 struct Extend<integer_sequence<T, Ints...>, SeqSize, 1> 3188 { 3189 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; 3190 }; 3191 3192 // Recursion helper for 'make_integer_sequence<T, N>'. 3193 // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'. 3194 template <typename T, size_t N> 3195 struct Gen 3196 { 3197 using type = 3198 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; 3199 }; 3200 3201 template <typename T> 3202 struct Gen<T, 0> 3203 { 3204 using type = integer_sequence<T>; 3205 }; 3206 3207 } // namespace utility_internal 3208 3209 // Compile-time sequences of integers 3210 3211 // make_integer_sequence 3212 // 3213 // This template alias is equivalent to 3214 // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in 3215 // replacement for C++14's `std::make_integer_sequence`. 3216 template <typename T, T N> 3217 using make_integer_sequence = typename utility_internal::Gen<T, N>::type; 3218 3219 // make_index_sequence 3220 // 3221 // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, 3222 // and is designed to be a drop-in replacement for C++14's 3223 // `std::make_index_sequence`. 3224 template <size_t N> 3225 using make_index_sequence = make_integer_sequence<size_t, N>; 3226 3227 // index_sequence_for 3228 // 3229 // Converts a typename pack into an index sequence of the same length, and 3230 // is designed to be a drop-in replacement for C++14's 3231 // `std::index_sequence_for()` 3232 template <typename... Ts> 3233 using index_sequence_for = make_index_sequence<sizeof...(Ts)>; 3234 3235 //// END OF CODE FROM GOOGLE ABSEIL 3236 3237 #endif 3238 3239 // dispatch utility (taken from ranges-v3) 3240 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {}; 3241 template<> struct priority_tag<0> {}; 3242 3243 // taken from ranges-v3 3244 template<typename T> 3245 struct static_const 3246 { 3247 static JSON_INLINE_VARIABLE constexpr T value{}; 3248 }; 3249 3250 #ifndef JSON_HAS_CPP_17 3251 template<typename T> 3252 constexpr T static_const<T>::value; 3253 #endif 3254 3255 template<typename T, typename... Args> 3256 constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args) 3257 { 3258 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}}; 3259 } 3260 3261 } // namespace detail 3262 NLOHMANN_JSON_NAMESPACE_END 3263 3264 // #include <nlohmann/detail/meta/type_traits.hpp> 3265 // __ _____ _____ _____ 3266 // __| | __| | | | JSON for Modern C++ 3267 // | | |__ | | | | | | version 3.11.3 3268 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3269 // 3270 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 3271 // SPDX-License-Identifier: MIT 3272 3273 3274 3275 #include <limits> // numeric_limits 3276 #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type 3277 #include <utility> // declval 3278 #include <tuple> // tuple 3279 #include <string> // char_traits 3280 3281 // #include <nlohmann/detail/iterators/iterator_traits.hpp> 3282 // __ _____ _____ _____ 3283 // __| | __| | | | JSON for Modern C++ 3284 // | | |__ | | | | | | version 3.11.3 3285 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3286 // 3287 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 3288 // SPDX-License-Identifier: MIT 3289 3290 3291 3292 #include <iterator> // random_access_iterator_tag 3293 3294 // #include <nlohmann/detail/abi_macros.hpp> 3295 3296 // #include <nlohmann/detail/meta/void_t.hpp> 3297 3298 // #include <nlohmann/detail/meta/cpp_future.hpp> 3299 3300 3301 NLOHMANN_JSON_NAMESPACE_BEGIN 3302 namespace detail 3303 { 3304 3305 template<typename It, typename = void> 3306 struct iterator_types {}; 3307 3308 template<typename It> 3309 struct iterator_types < 3310 It, 3311 void_t<typename It::difference_type, typename It::value_type, typename It::pointer, 3312 typename It::reference, typename It::iterator_category >> 3313 { 3314 using difference_type = typename It::difference_type; 3315 using value_type = typename It::value_type; 3316 using pointer = typename It::pointer; 3317 using reference = typename It::reference; 3318 using iterator_category = typename It::iterator_category; 3319 }; 3320 3321 // This is required as some compilers implement std::iterator_traits in a way that 3322 // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. 3323 template<typename T, typename = void> 3324 struct iterator_traits 3325 { 3326 }; 3327 3328 template<typename T> 3329 struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >> 3330 : iterator_types<T> 3331 { 3332 }; 3333 3334 template<typename T> 3335 struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>> 3336 { 3337 using iterator_category = std::random_access_iterator_tag; 3338 using value_type = T; 3339 using difference_type = ptrdiff_t; 3340 using pointer = T*; 3341 using reference = T&; 3342 }; 3343 3344 } // namespace detail 3345 NLOHMANN_JSON_NAMESPACE_END 3346 3347 // #include <nlohmann/detail/macro_scope.hpp> 3348 3349 // #include <nlohmann/detail/meta/call_std/begin.hpp> 3350 // __ _____ _____ _____ 3351 // __| | __| | | | JSON for Modern C++ 3352 // | | |__ | | | | | | version 3.11.3 3353 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3354 // 3355 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 3356 // SPDX-License-Identifier: MIT 3357 3358 3359 3360 // #include <nlohmann/detail/macro_scope.hpp> 3361 3362 3363 NLOHMANN_JSON_NAMESPACE_BEGIN 3364 3365 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); 3366 3367 NLOHMANN_JSON_NAMESPACE_END 3368 3369 // #include <nlohmann/detail/meta/call_std/end.hpp> 3370 // __ _____ _____ _____ 3371 // __| | __| | | | JSON for Modern C++ 3372 // | | |__ | | | | | | version 3.11.3 3373 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3374 // 3375 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 3376 // SPDX-License-Identifier: MIT 3377 3378 3379 3380 // #include <nlohmann/detail/macro_scope.hpp> 3381 3382 3383 NLOHMANN_JSON_NAMESPACE_BEGIN 3384 3385 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); 3386 3387 NLOHMANN_JSON_NAMESPACE_END 3388 3389 // #include <nlohmann/detail/meta/cpp_future.hpp> 3390 3391 // #include <nlohmann/detail/meta/detected.hpp> 3392 3393 // #include <nlohmann/json_fwd.hpp> 3394 // __ _____ _____ _____ 3395 // __| | __| | | | JSON for Modern C++ 3396 // | | |__ | | | | | | version 3.11.3 3397 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3398 // 3399 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 3400 // SPDX-License-Identifier: MIT 3401 3402 #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ 3403 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ 3404 3405 #include <cstdint> // int64_t, uint64_t 3406 #include <map> // map 3407 #include <memory> // allocator 3408 #include <string> // string 3409 #include <vector> // vector 3410 3411 // #include <nlohmann/detail/abi_macros.hpp> 3412 3413 3414 /*! 3415 @brief namespace for Niels Lohmann 3416 @see https://github.com/nlohmann 3417 @since version 1.0.0 3418 */ 3419 NLOHMANN_JSON_NAMESPACE_BEGIN 3420 3421 /*! 3422 @brief default JSONSerializer template argument 3423 3424 This serializer ignores the template arguments and uses ADL 3425 ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) 3426 for serialization. 3427 */ 3428 template<typename T = void, typename SFINAE = void> 3429 struct adl_serializer; 3430 3431 /// a class to store JSON values 3432 /// @sa https://json.nlohmann.me/api/basic_json/ 3433 template<template<typename U, typename V, typename... Args> class ObjectType = 3434 std::map, 3435 template<typename U, typename... Args> class ArrayType = std::vector, 3436 class StringType = std::string, class BooleanType = bool, 3437 class NumberIntegerType = std::int64_t, 3438 class NumberUnsignedType = std::uint64_t, 3439 class NumberFloatType = double, 3440 template<typename U> class AllocatorType = std::allocator, 3441 template<typename T, typename SFINAE = void> class JSONSerializer = 3442 adl_serializer, 3443 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError 3444 class CustomBaseClass = void> 3445 class basic_json; 3446 3447 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document 3448 /// @sa https://json.nlohmann.me/api/json_pointer/ 3449 template<typename RefStringType> 3450 class json_pointer; 3451 3452 /*! 3453 @brief default specialization 3454 @sa https://json.nlohmann.me/api/json/ 3455 */ 3456 using json = basic_json<>; 3457 3458 /// @brief a minimal map-like container that preserves insertion order 3459 /// @sa https://json.nlohmann.me/api/ordered_map/ 3460 template<class Key, class T, class IgnoredLess, class Allocator> 3461 struct ordered_map; 3462 3463 /// @brief specialization that maintains the insertion order of object keys 3464 /// @sa https://json.nlohmann.me/api/ordered_json/ 3465 using ordered_json = basic_json<nlohmann::ordered_map>; 3466 3467 NLOHMANN_JSON_NAMESPACE_END 3468 3469 #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ 3470 3471 3472 NLOHMANN_JSON_NAMESPACE_BEGIN 3473 /*! 3474 @brief detail namespace with internal helper functions 3475 3476 This namespace collects functions that should not be exposed, 3477 implementations of some @ref basic_json methods, and meta-programming helpers. 3478 3479 @since version 2.1.0 3480 */ 3481 namespace detail 3482 { 3483 3484 ///////////// 3485 // helpers // 3486 ///////////// 3487 3488 // Note to maintainers: 3489 // 3490 // Every trait in this file expects a non CV-qualified type. 3491 // The only exceptions are in the 'aliases for detected' section 3492 // (i.e. those of the form: decltype(T::member_function(std::declval<T>()))) 3493 // 3494 // In this case, T has to be properly CV-qualified to constraint the function arguments 3495 // (e.g. to_json(BasicJsonType&, const T&)) 3496 3497 template<typename> struct is_basic_json : std::false_type {}; 3498 3499 NLOHMANN_BASIC_JSON_TPL_DECLARATION 3500 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {}; 3501 3502 // used by exceptions create() member functions 3503 // true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t 3504 // false_type otherwise 3505 template<typename BasicJsonContext> 3506 struct is_basic_json_context : 3507 std::integral_constant < bool, 3508 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value 3509 || std::is_same<BasicJsonContext, std::nullptr_t>::value > 3510 {}; 3511 3512 ////////////////////// 3513 // json_ref helpers // 3514 ////////////////////// 3515 3516 template<typename> 3517 class json_ref; 3518 3519 template<typename> 3520 struct is_json_ref : std::false_type {}; 3521 3522 template<typename T> 3523 struct is_json_ref<json_ref<T>> : std::true_type {}; 3524 3525 ////////////////////////// 3526 // aliases for detected // 3527 ////////////////////////// 3528 3529 template<typename T> 3530 using mapped_type_t = typename T::mapped_type; 3531 3532 template<typename T> 3533 using key_type_t = typename T::key_type; 3534 3535 template<typename T> 3536 using value_type_t = typename T::value_type; 3537 3538 template<typename T> 3539 using difference_type_t = typename T::difference_type; 3540 3541 template<typename T> 3542 using pointer_t = typename T::pointer; 3543 3544 template<typename T> 3545 using reference_t = typename T::reference; 3546 3547 template<typename T> 3548 using iterator_category_t = typename T::iterator_category; 3549 3550 template<typename T, typename... Args> 3551 using to_json_function = decltype(T::to_json(std::declval<Args>()...)); 3552 3553 template<typename T, typename... Args> 3554 using from_json_function = decltype(T::from_json(std::declval<Args>()...)); 3555 3556 template<typename T, typename U> 3557 using get_template_function = decltype(std::declval<T>().template get<U>()); 3558 3559 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists 3560 template<typename BasicJsonType, typename T, typename = void> 3561 struct has_from_json : std::false_type {}; 3562 3563 // trait checking if j.get<T> is valid 3564 // use this trait instead of std::is_constructible or std::is_convertible, 3565 // both rely on, or make use of implicit conversions, and thus fail when T 3566 // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) 3567 template <typename BasicJsonType, typename T> 3568 struct is_getable 3569 { 3570 static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value; 3571 }; 3572 3573 template<typename BasicJsonType, typename T> 3574 struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> 3575 { 3576 using serializer = typename BasicJsonType::template json_serializer<T, void>; 3577 3578 static constexpr bool value = 3579 is_detected_exact<void, from_json_function, serializer, 3580 const BasicJsonType&, T&>::value; 3581 }; 3582 3583 // This trait checks if JSONSerializer<T>::from_json(json const&) exists 3584 // this overload is used for non-default-constructible user-defined-types 3585 template<typename BasicJsonType, typename T, typename = void> 3586 struct has_non_default_from_json : std::false_type {}; 3587 3588 template<typename BasicJsonType, typename T> 3589 struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> 3590 { 3591 using serializer = typename BasicJsonType::template json_serializer<T, void>; 3592 3593 static constexpr bool value = 3594 is_detected_exact<T, from_json_function, serializer, 3595 const BasicJsonType&>::value; 3596 }; 3597 3598 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists 3599 // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. 3600 template<typename BasicJsonType, typename T, typename = void> 3601 struct has_to_json : std::false_type {}; 3602 3603 template<typename BasicJsonType, typename T> 3604 struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> 3605 { 3606 using serializer = typename BasicJsonType::template json_serializer<T, void>; 3607 3608 static constexpr bool value = 3609 is_detected_exact<void, to_json_function, serializer, BasicJsonType&, 3610 T>::value; 3611 }; 3612 3613 template<typename T> 3614 using detect_key_compare = typename T::key_compare; 3615 3616 template<typename T> 3617 struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {}; 3618 3619 // obtains the actual object key comparator 3620 template<typename BasicJsonType> 3621 struct actual_object_comparator 3622 { 3623 using object_t = typename BasicJsonType::object_t; 3624 using object_comparator_t = typename BasicJsonType::default_object_comparator_t; 3625 using type = typename std::conditional < has_key_compare<object_t>::value, 3626 typename object_t::key_compare, object_comparator_t>::type; 3627 }; 3628 3629 template<typename BasicJsonType> 3630 using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type; 3631 3632 ///////////////// 3633 // char_traits // 3634 ///////////////// 3635 3636 // Primary template of char_traits calls std char_traits 3637 template<typename T> 3638 struct char_traits : std::char_traits<T> 3639 {}; 3640 3641 // Explicitly define char traits for unsigned char since it is not standard 3642 template<> 3643 struct char_traits<unsigned char> : std::char_traits<char> 3644 { 3645 using char_type = unsigned char; 3646 using int_type = uint64_t; 3647 3648 // Redefine to_int_type function 3649 static int_type to_int_type(char_type c) noexcept 3650 { 3651 return static_cast<int_type>(c); 3652 } 3653 3654 static char_type to_char_type(int_type i) noexcept 3655 { 3656 return static_cast<char_type>(i); 3657 } 3658 3659 static constexpr int_type eof() noexcept 3660 { 3661 return static_cast<int_type>(EOF); 3662 } 3663 }; 3664 3665 // Explicitly define char traits for signed char since it is not standard 3666 template<> 3667 struct char_traits<signed char> : std::char_traits<char> 3668 { 3669 using char_type = signed char; 3670 using int_type = uint64_t; 3671 3672 // Redefine to_int_type function 3673 static int_type to_int_type(char_type c) noexcept 3674 { 3675 return static_cast<int_type>(c); 3676 } 3677 3678 static char_type to_char_type(int_type i) noexcept 3679 { 3680 return static_cast<char_type>(i); 3681 } 3682 3683 static constexpr int_type eof() noexcept 3684 { 3685 return static_cast<int_type>(EOF); 3686 } 3687 }; 3688 3689 /////////////////// 3690 // is_ functions // 3691 /////////////////// 3692 3693 // https://en.cppreference.com/w/cpp/types/conjunction 3694 template<class...> struct conjunction : std::true_type { }; 3695 template<class B> struct conjunction<B> : B { }; 3696 template<class B, class... Bn> 3697 struct conjunction<B, Bn...> 3698 : std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {}; 3699 3700 // https://en.cppreference.com/w/cpp/types/negation 3701 template<class B> struct negation : std::integral_constant < bool, !B::value > { }; 3702 3703 // Reimplementation of is_constructible and is_default_constructible, due to them being broken for 3704 // std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). 3705 // This causes compile errors in e.g. clang 3.5 or gcc 4.9. 3706 template <typename T> 3707 struct is_default_constructible : std::is_default_constructible<T> {}; 3708 3709 template <typename T1, typename T2> 3710 struct is_default_constructible<std::pair<T1, T2>> 3711 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {}; 3712 3713 template <typename T1, typename T2> 3714 struct is_default_constructible<const std::pair<T1, T2>> 3715 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {}; 3716 3717 template <typename... Ts> 3718 struct is_default_constructible<std::tuple<Ts...>> 3719 : conjunction<is_default_constructible<Ts>...> {}; 3720 3721 template <typename... Ts> 3722 struct is_default_constructible<const std::tuple<Ts...>> 3723 : conjunction<is_default_constructible<Ts>...> {}; 3724 3725 template <typename T, typename... Args> 3726 struct is_constructible : std::is_constructible<T, Args...> {}; 3727 3728 template <typename T1, typename T2> 3729 struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {}; 3730 3731 template <typename T1, typename T2> 3732 struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {}; 3733 3734 template <typename... Ts> 3735 struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {}; 3736 3737 template <typename... Ts> 3738 struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {}; 3739 3740 template<typename T, typename = void> 3741 struct is_iterator_traits : std::false_type {}; 3742 3743 template<typename T> 3744 struct is_iterator_traits<iterator_traits<T>> 3745 { 3746 private: 3747 using traits = iterator_traits<T>; 3748 3749 public: 3750 static constexpr auto value = 3751 is_detected<value_type_t, traits>::value && 3752 is_detected<difference_type_t, traits>::value && 3753 is_detected<pointer_t, traits>::value && 3754 is_detected<iterator_category_t, traits>::value && 3755 is_detected<reference_t, traits>::value; 3756 }; 3757 3758 template<typename T> 3759 struct is_range 3760 { 3761 private: 3762 using t_ref = typename std::add_lvalue_reference<T>::type; 3763 3764 using iterator = detected_t<result_of_begin, t_ref>; 3765 using sentinel = detected_t<result_of_end, t_ref>; 3766 3767 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator 3768 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for 3769 // but reimplementing these would be too much work, as a lot of other concepts are used underneath 3770 static constexpr auto is_iterator_begin = 3771 is_iterator_traits<iterator_traits<iterator>>::value; 3772 3773 public: 3774 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin; 3775 }; 3776 3777 template<typename R> 3778 using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>; 3779 3780 template<typename T> 3781 using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>; 3782 3783 // The following implementation of is_complete_type is taken from 3784 // https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ 3785 // and is written by Xiang Fan who agreed to using it in this library. 3786 3787 template<typename T, typename = void> 3788 struct is_complete_type : std::false_type {}; 3789 3790 template<typename T> 3791 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {}; 3792 3793 template<typename BasicJsonType, typename CompatibleObjectType, 3794 typename = void> 3795 struct is_compatible_object_type_impl : std::false_type {}; 3796 3797 template<typename BasicJsonType, typename CompatibleObjectType> 3798 struct is_compatible_object_type_impl < 3799 BasicJsonType, CompatibleObjectType, 3800 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&& 3801 is_detected<key_type_t, CompatibleObjectType>::value >> 3802 { 3803 using object_t = typename BasicJsonType::object_t; 3804 3805 // macOS's is_constructible does not play well with nonesuch... 3806 static constexpr bool value = 3807 is_constructible<typename object_t::key_type, 3808 typename CompatibleObjectType::key_type>::value && 3809 is_constructible<typename object_t::mapped_type, 3810 typename CompatibleObjectType::mapped_type>::value; 3811 }; 3812 3813 template<typename BasicJsonType, typename CompatibleObjectType> 3814 struct is_compatible_object_type 3815 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {}; 3816 3817 template<typename BasicJsonType, typename ConstructibleObjectType, 3818 typename = void> 3819 struct is_constructible_object_type_impl : std::false_type {}; 3820 3821 template<typename BasicJsonType, typename ConstructibleObjectType> 3822 struct is_constructible_object_type_impl < 3823 BasicJsonType, ConstructibleObjectType, 3824 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&& 3825 is_detected<key_type_t, ConstructibleObjectType>::value >> 3826 { 3827 using object_t = typename BasicJsonType::object_t; 3828 3829 static constexpr bool value = 3830 (is_default_constructible<ConstructibleObjectType>::value && 3831 (std::is_move_assignable<ConstructibleObjectType>::value || 3832 std::is_copy_assignable<ConstructibleObjectType>::value) && 3833 (is_constructible<typename ConstructibleObjectType::key_type, 3834 typename object_t::key_type>::value && 3835 std::is_same < 3836 typename object_t::mapped_type, 3837 typename ConstructibleObjectType::mapped_type >::value)) || 3838 (has_from_json<BasicJsonType, 3839 typename ConstructibleObjectType::mapped_type>::value || 3840 has_non_default_from_json < 3841 BasicJsonType, 3842 typename ConstructibleObjectType::mapped_type >::value); 3843 }; 3844 3845 template<typename BasicJsonType, typename ConstructibleObjectType> 3846 struct is_constructible_object_type 3847 : is_constructible_object_type_impl<BasicJsonType, 3848 ConstructibleObjectType> {}; 3849 3850 template<typename BasicJsonType, typename CompatibleStringType> 3851 struct is_compatible_string_type 3852 { 3853 static constexpr auto value = 3854 is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value; 3855 }; 3856 3857 template<typename BasicJsonType, typename ConstructibleStringType> 3858 struct is_constructible_string_type 3859 { 3860 // launder type through decltype() to fix compilation failure on ICPC 3861 #ifdef __INTEL_COMPILER 3862 using laundered_type = decltype(std::declval<ConstructibleStringType>()); 3863 #else 3864 using laundered_type = ConstructibleStringType; 3865 #endif 3866 3867 static constexpr auto value = 3868 conjunction < 3869 is_constructible<laundered_type, typename BasicJsonType::string_t>, 3870 is_detected_exact<typename BasicJsonType::string_t::value_type, 3871 value_type_t, laundered_type >>::value; 3872 }; 3873 3874 template<typename BasicJsonType, typename CompatibleArrayType, typename = void> 3875 struct is_compatible_array_type_impl : std::false_type {}; 3876 3877 template<typename BasicJsonType, typename CompatibleArrayType> 3878 struct is_compatible_array_type_impl < 3879 BasicJsonType, CompatibleArrayType, 3880 enable_if_t < 3881 is_detected<iterator_t, CompatibleArrayType>::value&& 3882 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&& 3883 // special case for types like std::filesystem::path whose iterator's value_type are themselves 3884 // c.f. https://github.com/nlohmann/json/pull/3073 3885 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >> 3886 { 3887 static constexpr bool value = 3888 is_constructible<BasicJsonType, 3889 range_value_t<CompatibleArrayType>>::value; 3890 }; 3891 3892 template<typename BasicJsonType, typename CompatibleArrayType> 3893 struct is_compatible_array_type 3894 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {}; 3895 3896 template<typename BasicJsonType, typename ConstructibleArrayType, typename = void> 3897 struct is_constructible_array_type_impl : std::false_type {}; 3898 3899 template<typename BasicJsonType, typename ConstructibleArrayType> 3900 struct is_constructible_array_type_impl < 3901 BasicJsonType, ConstructibleArrayType, 3902 enable_if_t<std::is_same<ConstructibleArrayType, 3903 typename BasicJsonType::value_type>::value >> 3904 : std::true_type {}; 3905 3906 template<typename BasicJsonType, typename ConstructibleArrayType> 3907 struct is_constructible_array_type_impl < 3908 BasicJsonType, ConstructibleArrayType, 3909 enable_if_t < !std::is_same<ConstructibleArrayType, 3910 typename BasicJsonType::value_type>::value&& 3911 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&& 3912 is_default_constructible<ConstructibleArrayType>::value&& 3913 (std::is_move_assignable<ConstructibleArrayType>::value || 3914 std::is_copy_assignable<ConstructibleArrayType>::value)&& 3915 is_detected<iterator_t, ConstructibleArrayType>::value&& 3916 is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&& 3917 is_detected<range_value_t, ConstructibleArrayType>::value&& 3918 // special case for types like std::filesystem::path whose iterator's value_type are themselves 3919 // c.f. https://github.com/nlohmann/json/pull/3073 3920 !std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&& 3921 is_complete_type < 3922 detected_t<range_value_t, ConstructibleArrayType >>::value >> 3923 { 3924 using value_type = range_value_t<ConstructibleArrayType>; 3925 3926 static constexpr bool value = 3927 std::is_same<value_type, 3928 typename BasicJsonType::array_t::value_type>::value || 3929 has_from_json<BasicJsonType, 3930 value_type>::value || 3931 has_non_default_from_json < 3932 BasicJsonType, 3933 value_type >::value; 3934 }; 3935 3936 template<typename BasicJsonType, typename ConstructibleArrayType> 3937 struct is_constructible_array_type 3938 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {}; 3939 3940 template<typename RealIntegerType, typename CompatibleNumberIntegerType, 3941 typename = void> 3942 struct is_compatible_integer_type_impl : std::false_type {}; 3943 3944 template<typename RealIntegerType, typename CompatibleNumberIntegerType> 3945 struct is_compatible_integer_type_impl < 3946 RealIntegerType, CompatibleNumberIntegerType, 3947 enable_if_t < std::is_integral<RealIntegerType>::value&& 3948 std::is_integral<CompatibleNumberIntegerType>::value&& 3949 !std::is_same<bool, CompatibleNumberIntegerType>::value >> 3950 { 3951 // is there an assert somewhere on overflows? 3952 using RealLimits = std::numeric_limits<RealIntegerType>; 3953 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>; 3954 3955 static constexpr auto value = 3956 is_constructible<RealIntegerType, 3957 CompatibleNumberIntegerType>::value && 3958 CompatibleLimits::is_integer && 3959 RealLimits::is_signed == CompatibleLimits::is_signed; 3960 }; 3961 3962 template<typename RealIntegerType, typename CompatibleNumberIntegerType> 3963 struct is_compatible_integer_type 3964 : is_compatible_integer_type_impl<RealIntegerType, 3965 CompatibleNumberIntegerType> {}; 3966 3967 template<typename BasicJsonType, typename CompatibleType, typename = void> 3968 struct is_compatible_type_impl: std::false_type {}; 3969 3970 template<typename BasicJsonType, typename CompatibleType> 3971 struct is_compatible_type_impl < 3972 BasicJsonType, CompatibleType, 3973 enable_if_t<is_complete_type<CompatibleType>::value >> 3974 { 3975 static constexpr bool value = 3976 has_to_json<BasicJsonType, CompatibleType>::value; 3977 }; 3978 3979 template<typename BasicJsonType, typename CompatibleType> 3980 struct is_compatible_type 3981 : is_compatible_type_impl<BasicJsonType, CompatibleType> {}; 3982 3983 template<typename T1, typename T2> 3984 struct is_constructible_tuple : std::false_type {}; 3985 3986 template<typename T1, typename... Args> 3987 struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {}; 3988 3989 template<typename BasicJsonType, typename T> 3990 struct is_json_iterator_of : std::false_type {}; 3991 3992 template<typename BasicJsonType> 3993 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {}; 3994 3995 template<typename BasicJsonType> 3996 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type 3997 {}; 3998 3999 // checks if a given type T is a template specialization of Primary 4000 template<template <typename...> class Primary, typename T> 4001 struct is_specialization_of : std::false_type {}; 4002 4003 template<template <typename...> class Primary, typename... Args> 4004 struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {}; 4005 4006 template<typename T> 4007 using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>; 4008 4009 // checks if A and B are comparable using Compare functor 4010 template<typename Compare, typename A, typename B, typename = void> 4011 struct is_comparable : std::false_type {}; 4012 4013 template<typename Compare, typename A, typename B> 4014 struct is_comparable<Compare, A, B, void_t< 4015 decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())), 4016 decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>())) 4017 >> : std::true_type {}; 4018 4019 template<typename T> 4020 using detect_is_transparent = typename T::is_transparent; 4021 4022 // type trait to check if KeyType can be used as object key (without a BasicJsonType) 4023 // see is_usable_as_basic_json_key_type below 4024 template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true, 4025 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>> 4026 using is_usable_as_key_type = typename std::conditional < 4027 is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value 4028 && !(ExcludeObjectKeyType && std::is_same<KeyType, 4029 ObjectKeyType>::value) 4030 && (!RequireTransparentComparator 4031 || is_detected <detect_is_transparent, Comparator>::value) 4032 && !is_json_pointer<KeyType>::value, 4033 std::true_type, 4034 std::false_type >::type; 4035 4036 // type trait to check if KeyType can be used as object key 4037 // true if: 4038 // - KeyType is comparable with BasicJsonType::object_t::key_type 4039 // - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type 4040 // - the comparator is transparent or RequireTransparentComparator is false 4041 // - KeyType is not a JSON iterator or json_pointer 4042 template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true, 4043 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>> 4044 using is_usable_as_basic_json_key_type = typename std::conditional < 4045 is_usable_as_key_type<typename BasicJsonType::object_comparator_t, 4046 typename BasicJsonType::object_t::key_type, KeyTypeCVRef, 4047 RequireTransparentComparator, ExcludeObjectKeyType>::value 4048 && !is_json_iterator_of<BasicJsonType, KeyType>::value, 4049 std::true_type, 4050 std::false_type >::type; 4051 4052 template<typename ObjectType, typename KeyType> 4053 using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>())); 4054 4055 // type trait to check if object_t has an erase() member functions accepting KeyType 4056 template<typename BasicJsonType, typename KeyType> 4057 using has_erase_with_key_type = typename std::conditional < 4058 is_detected < 4059 detect_erase_with_key_type, 4060 typename BasicJsonType::object_t, KeyType >::value, 4061 std::true_type, 4062 std::false_type >::type; 4063 4064 // a naive helper to check if a type is an ordered_map (exploits the fact that 4065 // ordered_map inherits capacity() from std::vector) 4066 template <typename T> 4067 struct is_ordered_map 4068 { 4069 using one = char; 4070 4071 struct two 4072 { 4073 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 4074 }; 4075 4076 template <typename C> static one test( decltype(&C::capacity) ) ; 4077 template <typename C> static two test(...); 4078 4079 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 4080 }; 4081 4082 // to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324) 4083 template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 > 4084 T conditional_static_cast(U value) 4085 { 4086 return static_cast<T>(value); 4087 } 4088 4089 template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0> 4090 T conditional_static_cast(U value) 4091 { 4092 return value; 4093 } 4094 4095 template<typename... Types> 4096 using all_integral = conjunction<std::is_integral<Types>...>; 4097 4098 template<typename... Types> 4099 using all_signed = conjunction<std::is_signed<Types>...>; 4100 4101 template<typename... Types> 4102 using all_unsigned = conjunction<std::is_unsigned<Types>...>; 4103 4104 // there's a disjunction trait in another PR; replace when merged 4105 template<typename... Types> 4106 using same_sign = std::integral_constant < bool, 4107 all_signed<Types...>::value || all_unsigned<Types...>::value >; 4108 4109 template<typename OfType, typename T> 4110 using never_out_of_range = std::integral_constant < bool, 4111 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType))) 4112 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >; 4113 4114 template<typename OfType, typename T, 4115 bool OfTypeSigned = std::is_signed<OfType>::value, 4116 bool TSigned = std::is_signed<T>::value> 4117 struct value_in_range_of_impl2; 4118 4119 template<typename OfType, typename T> 4120 struct value_in_range_of_impl2<OfType, T, false, false> 4121 { 4122 static constexpr bool test(T val) 4123 { 4124 using CommonType = typename std::common_type<OfType, T>::type; 4125 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); 4126 } 4127 }; 4128 4129 template<typename OfType, typename T> 4130 struct value_in_range_of_impl2<OfType, T, true, false> 4131 { 4132 static constexpr bool test(T val) 4133 { 4134 using CommonType = typename std::common_type<OfType, T>::type; 4135 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); 4136 } 4137 }; 4138 4139 template<typename OfType, typename T> 4140 struct value_in_range_of_impl2<OfType, T, false, true> 4141 { 4142 static constexpr bool test(T val) 4143 { 4144 using CommonType = typename std::common_type<OfType, T>::type; 4145 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); 4146 } 4147 }; 4148 4149 template<typename OfType, typename T> 4150 struct value_in_range_of_impl2<OfType, T, true, true> 4151 { 4152 static constexpr bool test(T val) 4153 { 4154 using CommonType = typename std::common_type<OfType, T>::type; 4155 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)()) 4156 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); 4157 } 4158 }; 4159 4160 template<typename OfType, typename T, 4161 bool NeverOutOfRange = never_out_of_range<OfType, T>::value, 4162 typename = detail::enable_if_t<all_integral<OfType, T>::value>> 4163 struct value_in_range_of_impl1; 4164 4165 template<typename OfType, typename T> 4166 struct value_in_range_of_impl1<OfType, T, false> 4167 { 4168 static constexpr bool test(T val) 4169 { 4170 return value_in_range_of_impl2<OfType, T>::test(val); 4171 } 4172 }; 4173 4174 template<typename OfType, typename T> 4175 struct value_in_range_of_impl1<OfType, T, true> 4176 { 4177 static constexpr bool test(T /*val*/) 4178 { 4179 return true; 4180 } 4181 }; 4182 4183 template<typename OfType, typename T> 4184 constexpr bool value_in_range_of(T val) 4185 { 4186 return value_in_range_of_impl1<OfType, T>::test(val); 4187 } 4188 4189 template<bool Value> 4190 using bool_constant = std::integral_constant<bool, Value>; 4191 4192 /////////////////////////////////////////////////////////////////////////////// 4193 // is_c_string 4194 /////////////////////////////////////////////////////////////////////////////// 4195 4196 namespace impl 4197 { 4198 4199 template<typename T> 4200 constexpr bool is_c_string() 4201 { 4202 using TUnExt = typename std::remove_extent<T>::type; 4203 using TUnCVExt = typename std::remove_cv<TUnExt>::type; 4204 using TUnPtr = typename std::remove_pointer<T>::type; 4205 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type; 4206 return 4207 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value) 4208 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value); 4209 } 4210 4211 } // namespace impl 4212 4213 // checks whether T is a [cv] char */[cv] char[] C string 4214 template<typename T> 4215 struct is_c_string : bool_constant<impl::is_c_string<T>()> {}; 4216 4217 template<typename T> 4218 using is_c_string_uncvref = is_c_string<uncvref_t<T>>; 4219 4220 /////////////////////////////////////////////////////////////////////////////// 4221 // is_transparent 4222 /////////////////////////////////////////////////////////////////////////////// 4223 4224 namespace impl 4225 { 4226 4227 template<typename T> 4228 constexpr bool is_transparent() 4229 { 4230 return is_detected<detect_is_transparent, T>::value; 4231 } 4232 4233 } // namespace impl 4234 4235 // checks whether T has a member named is_transparent 4236 template<typename T> 4237 struct is_transparent : bool_constant<impl::is_transparent<T>()> {}; 4238 4239 /////////////////////////////////////////////////////////////////////////////// 4240 4241 } // namespace detail 4242 NLOHMANN_JSON_NAMESPACE_END 4243 4244 // #include <nlohmann/detail/string_concat.hpp> 4245 // __ _____ _____ _____ 4246 // __| | __| | | | JSON for Modern C++ 4247 // | | |__ | | | | | | version 3.11.3 4248 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 4249 // 4250 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 4251 // SPDX-License-Identifier: MIT 4252 4253 4254 4255 #include <cstring> // strlen 4256 #include <string> // string 4257 #include <utility> // forward 4258 4259 // #include <nlohmann/detail/meta/cpp_future.hpp> 4260 4261 // #include <nlohmann/detail/meta/detected.hpp> 4262 4263 4264 NLOHMANN_JSON_NAMESPACE_BEGIN 4265 namespace detail 4266 { 4267 4268 inline std::size_t concat_length() 4269 { 4270 return 0; 4271 } 4272 4273 template<typename... Args> 4274 inline std::size_t concat_length(const char* cstr, const Args& ... rest); 4275 4276 template<typename StringType, typename... Args> 4277 inline std::size_t concat_length(const StringType& str, const Args& ... rest); 4278 4279 template<typename... Args> 4280 inline std::size_t concat_length(const char /*c*/, const Args& ... rest) 4281 { 4282 return 1 + concat_length(rest...); 4283 } 4284 4285 template<typename... Args> 4286 inline std::size_t concat_length(const char* cstr, const Args& ... rest) 4287 { 4288 // cppcheck-suppress ignoredReturnValue 4289 return ::strlen(cstr) + concat_length(rest...); 4290 } 4291 4292 template<typename StringType, typename... Args> 4293 inline std::size_t concat_length(const StringType& str, const Args& ... rest) 4294 { 4295 return str.size() + concat_length(rest...); 4296 } 4297 4298 template<typename OutStringType> 4299 inline void concat_into(OutStringType& /*out*/) 4300 {} 4301 4302 template<typename StringType, typename Arg> 4303 using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ())); 4304 4305 template<typename StringType, typename Arg> 4306 using detect_string_can_append = is_detected<string_can_append, StringType, Arg>; 4307 4308 template<typename StringType, typename Arg> 4309 using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ()); 4310 4311 template<typename StringType, typename Arg> 4312 using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>; 4313 4314 template<typename StringType, typename Arg> 4315 using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end())); 4316 4317 template<typename StringType, typename Arg> 4318 using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>; 4319 4320 template<typename StringType, typename Arg> 4321 using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size())); 4322 4323 template<typename StringType, typename Arg> 4324 using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>; 4325 4326 template < typename OutStringType, typename Arg, typename... Args, 4327 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4328 && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 > 4329 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest); 4330 4331 template < typename OutStringType, typename Arg, typename... Args, 4332 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4333 && !detect_string_can_append_op<OutStringType, Arg>::value 4334 && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 > 4335 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); 4336 4337 template < typename OutStringType, typename Arg, typename... Args, 4338 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4339 && !detect_string_can_append_op<OutStringType, Arg>::value 4340 && !detect_string_can_append_iter<OutStringType, Arg>::value 4341 && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 > 4342 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); 4343 4344 template<typename OutStringType, typename Arg, typename... Args, 4345 enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0> 4346 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest) 4347 { 4348 out.append(std::forward<Arg>(arg)); 4349 concat_into(out, std::forward<Args>(rest)...); 4350 } 4351 4352 template < typename OutStringType, typename Arg, typename... Args, 4353 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4354 && detect_string_can_append_op<OutStringType, Arg>::value, int > > 4355 inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest) 4356 { 4357 out += std::forward<Arg>(arg); 4358 concat_into(out, std::forward<Args>(rest)...); 4359 } 4360 4361 template < typename OutStringType, typename Arg, typename... Args, 4362 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4363 && !detect_string_can_append_op<OutStringType, Arg>::value 4364 && detect_string_can_append_iter<OutStringType, Arg>::value, int > > 4365 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) 4366 { 4367 out.append(arg.begin(), arg.end()); 4368 concat_into(out, std::forward<Args>(rest)...); 4369 } 4370 4371 template < typename OutStringType, typename Arg, typename... Args, 4372 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4373 && !detect_string_can_append_op<OutStringType, Arg>::value 4374 && !detect_string_can_append_iter<OutStringType, Arg>::value 4375 && detect_string_can_append_data<OutStringType, Arg>::value, int > > 4376 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) 4377 { 4378 out.append(arg.data(), arg.size()); 4379 concat_into(out, std::forward<Args>(rest)...); 4380 } 4381 4382 template<typename OutStringType = std::string, typename... Args> 4383 inline OutStringType concat(Args && ... args) 4384 { 4385 OutStringType str; 4386 str.reserve(concat_length(args...)); 4387 concat_into(str, std::forward<Args>(args)...); 4388 return str; 4389 } 4390 4391 } // namespace detail 4392 NLOHMANN_JSON_NAMESPACE_END 4393 4394 4395 // With -Wweak-vtables, Clang will complain about the exception classes as they 4396 // have no out-of-line virtual method definitions and their vtable will be 4397 // emitted in every translation unit. This issue cannot be fixed with a 4398 // header-only library as there is no implementation file to move these 4399 // functions to. As a result, we suppress this warning here to avoid client 4400 // code to stumble over this. See https://github.com/nlohmann/json/issues/4087 4401 // for a discussion. 4402 #if defined(__clang__) 4403 #pragma clang diagnostic push 4404 #pragma clang diagnostic ignored "-Wweak-vtables" 4405 #endif 4406 4407 NLOHMANN_JSON_NAMESPACE_BEGIN 4408 namespace detail 4409 { 4410 4411 //////////////// 4412 // exceptions // 4413 //////////////// 4414 4415 /// @brief general exception of the @ref basic_json class 4416 /// @sa https://json.nlohmann.me/api/basic_json/exception/ 4417 class exception : public std::exception 4418 { 4419 public: 4420 /// returns the explanatory string 4421 const char* what() const noexcept override 4422 { 4423 return m.what(); 4424 } 4425 4426 /// the id of the exception 4427 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) 4428 4429 protected: 4430 JSON_HEDLEY_NON_NULL(3) 4431 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing) 4432 4433 static std::string name(const std::string& ename, int id_) 4434 { 4435 return concat("[json.exception.", ename, '.', std::to_string(id_), "] "); 4436 } 4437 4438 static std::string diagnostics(std::nullptr_t /*leaf_element*/) 4439 { 4440 return ""; 4441 } 4442 4443 template<typename BasicJsonType> 4444 static std::string diagnostics(const BasicJsonType* leaf_element) 4445 { 4446 #if JSON_DIAGNOSTICS 4447 std::vector<std::string> tokens; 4448 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent) 4449 { 4450 switch (current->m_parent->type()) 4451 { 4452 case value_t::array: 4453 { 4454 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i) 4455 { 4456 if (¤t->m_parent->m_data.m_value.array->operator[](i) == current) 4457 { 4458 tokens.emplace_back(std::to_string(i)); 4459 break; 4460 } 4461 } 4462 break; 4463 } 4464 4465 case value_t::object: 4466 { 4467 for (const auto& element : *current->m_parent->m_data.m_value.object) 4468 { 4469 if (&element.second == current) 4470 { 4471 tokens.emplace_back(element.first.c_str()); 4472 break; 4473 } 4474 } 4475 break; 4476 } 4477 4478 case value_t::null: // LCOV_EXCL_LINE 4479 case value_t::string: // LCOV_EXCL_LINE 4480 case value_t::boolean: // LCOV_EXCL_LINE 4481 case value_t::number_integer: // LCOV_EXCL_LINE 4482 case value_t::number_unsigned: // LCOV_EXCL_LINE 4483 case value_t::number_float: // LCOV_EXCL_LINE 4484 case value_t::binary: // LCOV_EXCL_LINE 4485 case value_t::discarded: // LCOV_EXCL_LINE 4486 default: // LCOV_EXCL_LINE 4487 break; // LCOV_EXCL_LINE 4488 } 4489 } 4490 4491 if (tokens.empty()) 4492 { 4493 return ""; 4494 } 4495 4496 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, 4497 [](const std::string & a, const std::string & b) 4498 { 4499 return concat(a, '/', detail::escape(b)); 4500 }); 4501 return concat('(', str, ") "); 4502 #else 4503 static_cast<void>(leaf_element); 4504 return ""; 4505 #endif 4506 } 4507 4508 private: 4509 /// an exception object as storage for error messages 4510 std::runtime_error m; 4511 }; 4512 4513 /// @brief exception indicating a parse error 4514 /// @sa https://json.nlohmann.me/api/basic_json/parse_error/ 4515 class parse_error : public exception 4516 { 4517 public: 4518 /*! 4519 @brief create a parse error exception 4520 @param[in] id_ the id of the exception 4521 @param[in] pos the position where the error occurred (or with 4522 chars_read_total=0 if the position cannot be 4523 determined) 4524 @param[in] what_arg the explanatory string 4525 @return parse_error object 4526 */ 4527 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4528 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context) 4529 { 4530 const std::string w = concat(exception::name("parse_error", id_), "parse error", 4531 position_string(pos), ": ", exception::diagnostics(context), what_arg); 4532 return {id_, pos.chars_read_total, w.c_str()}; 4533 } 4534 4535 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4536 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context) 4537 { 4538 const std::string w = concat(exception::name("parse_error", id_), "parse error", 4539 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""), 4540 ": ", exception::diagnostics(context), what_arg); 4541 return {id_, byte_, w.c_str()}; 4542 } 4543 4544 /*! 4545 @brief byte index of the parse error 4546 4547 The byte index of the last read character in the input file. 4548 4549 @note For an input with n bytes, 1 is the index of the first character and 4550 n+1 is the index of the terminating null byte or the end of file. 4551 This also holds true when reading a byte vector (CBOR or MessagePack). 4552 */ 4553 const std::size_t byte; 4554 4555 private: 4556 parse_error(int id_, std::size_t byte_, const char* what_arg) 4557 : exception(id_, what_arg), byte(byte_) {} 4558 4559 static std::string position_string(const position_t& pos) 4560 { 4561 return concat(" at line ", std::to_string(pos.lines_read + 1), 4562 ", column ", std::to_string(pos.chars_read_current_line)); 4563 } 4564 }; 4565 4566 /// @brief exception indicating errors with iterators 4567 /// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/ 4568 class invalid_iterator : public exception 4569 { 4570 public: 4571 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4572 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context) 4573 { 4574 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg); 4575 return {id_, w.c_str()}; 4576 } 4577 4578 private: 4579 JSON_HEDLEY_NON_NULL(3) 4580 invalid_iterator(int id_, const char* what_arg) 4581 : exception(id_, what_arg) {} 4582 }; 4583 4584 /// @brief exception indicating executing a member function with a wrong type 4585 /// @sa https://json.nlohmann.me/api/basic_json/type_error/ 4586 class type_error : public exception 4587 { 4588 public: 4589 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4590 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context) 4591 { 4592 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg); 4593 return {id_, w.c_str()}; 4594 } 4595 4596 private: 4597 JSON_HEDLEY_NON_NULL(3) 4598 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} 4599 }; 4600 4601 /// @brief exception indicating access out of the defined range 4602 /// @sa https://json.nlohmann.me/api/basic_json/out_of_range/ 4603 class out_of_range : public exception 4604 { 4605 public: 4606 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4607 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context) 4608 { 4609 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg); 4610 return {id_, w.c_str()}; 4611 } 4612 4613 private: 4614 JSON_HEDLEY_NON_NULL(3) 4615 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} 4616 }; 4617 4618 /// @brief exception indicating other library errors 4619 /// @sa https://json.nlohmann.me/api/basic_json/other_error/ 4620 class other_error : public exception 4621 { 4622 public: 4623 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4624 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context) 4625 { 4626 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg); 4627 return {id_, w.c_str()}; 4628 } 4629 4630 private: 4631 JSON_HEDLEY_NON_NULL(3) 4632 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} 4633 }; 4634 4635 } // namespace detail 4636 NLOHMANN_JSON_NAMESPACE_END 4637 4638 #if defined(__clang__) 4639 #pragma clang diagnostic pop 4640 #endif 4641 4642 // #include <nlohmann/detail/macro_scope.hpp> 4643 4644 // #include <nlohmann/detail/meta/cpp_future.hpp> 4645 4646 // #include <nlohmann/detail/meta/identity_tag.hpp> 4647 // __ _____ _____ _____ 4648 // __| | __| | | | JSON for Modern C++ 4649 // | | |__ | | | | | | version 3.11.3 4650 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 4651 // 4652 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 4653 // SPDX-License-Identifier: MIT 4654 4655 4656 4657 // #include <nlohmann/detail/abi_macros.hpp> 4658 4659 4660 NLOHMANN_JSON_NAMESPACE_BEGIN 4661 namespace detail 4662 { 4663 4664 // dispatching helper struct 4665 template <class T> struct identity_tag {}; 4666 4667 } // namespace detail 4668 NLOHMANN_JSON_NAMESPACE_END 4669 4670 // #include <nlohmann/detail/meta/std_fs.hpp> 4671 // __ _____ _____ _____ 4672 // __| | __| | | | JSON for Modern C++ 4673 // | | |__ | | | | | | version 3.11.3 4674 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 4675 // 4676 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 4677 // SPDX-License-Identifier: MIT 4678 4679 4680 4681 // #include <nlohmann/detail/macro_scope.hpp> 4682 4683 4684 #if JSON_HAS_EXPERIMENTAL_FILESYSTEM 4685 #include <experimental/filesystem> 4686 NLOHMANN_JSON_NAMESPACE_BEGIN 4687 namespace detail 4688 { 4689 namespace std_fs = std::experimental::filesystem; 4690 } // namespace detail 4691 NLOHMANN_JSON_NAMESPACE_END 4692 #elif JSON_HAS_FILESYSTEM 4693 #include <filesystem> // NOLINT(build/c++17) 4694 NLOHMANN_JSON_NAMESPACE_BEGIN 4695 namespace detail 4696 { 4697 namespace std_fs = std::filesystem; 4698 } // namespace detail 4699 NLOHMANN_JSON_NAMESPACE_END 4700 #endif 4701 4702 // #include <nlohmann/detail/meta/type_traits.hpp> 4703 4704 // #include <nlohmann/detail/string_concat.hpp> 4705 4706 // #include <nlohmann/detail/value_t.hpp> 4707 4708 4709 NLOHMANN_JSON_NAMESPACE_BEGIN 4710 namespace detail 4711 { 4712 4713 template<typename BasicJsonType> 4714 inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n) 4715 { 4716 if (JSON_HEDLEY_UNLIKELY(!j.is_null())) 4717 { 4718 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j)); 4719 } 4720 n = nullptr; 4721 } 4722 4723 #ifdef JSON_HAS_CPP_17 4724 #ifndef JSON_USE_IMPLICIT_CONVERSIONS 4725 template<typename BasicJsonType, typename T> 4726 void from_json(const BasicJsonType& j, std::optional<T>& opt) 4727 { 4728 if (j.is_null()) 4729 { 4730 opt = std::nullopt; 4731 } 4732 else 4733 { 4734 opt.emplace(j.template get<T>()); 4735 } 4736 } 4737 4738 #endif // JSON_USE_IMPLICIT_CONVERSIONS 4739 #endif // JSON_HAS_CPP_17 4740 4741 // overloads for basic_json template parameters 4742 template < typename BasicJsonType, typename ArithmeticType, 4743 enable_if_t < std::is_arithmetic<ArithmeticType>::value&& 4744 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, 4745 int > = 0 > 4746 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) 4747 { 4748 switch (static_cast<value_t>(j)) 4749 { 4750 case value_t::number_unsigned: 4751 { 4752 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>()); 4753 break; 4754 } 4755 case value_t::number_integer: 4756 { 4757 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>()); 4758 break; 4759 } 4760 case value_t::number_float: 4761 { 4762 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); 4763 break; 4764 } 4765 4766 case value_t::null: 4767 case value_t::object: 4768 case value_t::array: 4769 case value_t::string: 4770 case value_t::boolean: 4771 case value_t::binary: 4772 case value_t::discarded: 4773 default: 4774 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); 4775 } 4776 } 4777 4778 template<typename BasicJsonType> 4779 inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) 4780 { 4781 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) 4782 { 4783 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j)); 4784 } 4785 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>(); 4786 } 4787 4788 template<typename BasicJsonType> 4789 inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) 4790 { 4791 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) 4792 { 4793 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); 4794 } 4795 s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); 4796 } 4797 4798 template < 4799 typename BasicJsonType, typename StringType, 4800 enable_if_t < 4801 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value 4802 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value 4803 && !std::is_same<typename BasicJsonType::string_t, StringType>::value 4804 && !is_json_ref<StringType>::value, int > = 0 > 4805 inline void from_json(const BasicJsonType& j, StringType& s) 4806 { 4807 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) 4808 { 4809 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); 4810 } 4811 4812 s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); 4813 } 4814 4815 template<typename BasicJsonType> 4816 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) 4817 { 4818 get_arithmetic_value(j, val); 4819 } 4820 4821 template<typename BasicJsonType> 4822 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) 4823 { 4824 get_arithmetic_value(j, val); 4825 } 4826 4827 template<typename BasicJsonType> 4828 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) 4829 { 4830 get_arithmetic_value(j, val); 4831 } 4832 4833 #if !JSON_DISABLE_ENUM_SERIALIZATION 4834 template<typename BasicJsonType, typename EnumType, 4835 enable_if_t<std::is_enum<EnumType>::value, int> = 0> 4836 inline void from_json(const BasicJsonType& j, EnumType& e) 4837 { 4838 typename std::underlying_type<EnumType>::type val; 4839 get_arithmetic_value(j, val); 4840 e = static_cast<EnumType>(val); 4841 } 4842 #endif // JSON_DISABLE_ENUM_SERIALIZATION 4843 4844 // forward_list doesn't have an insert method 4845 template<typename BasicJsonType, typename T, typename Allocator, 4846 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0> 4847 inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l) 4848 { 4849 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 4850 { 4851 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 4852 } 4853 l.clear(); 4854 std::transform(j.rbegin(), j.rend(), 4855 std::front_inserter(l), [](const BasicJsonType & i) 4856 { 4857 return i.template get<T>(); 4858 }); 4859 } 4860 4861 // valarray doesn't have an insert method 4862 template<typename BasicJsonType, typename T, 4863 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0> 4864 inline void from_json(const BasicJsonType& j, std::valarray<T>& l) 4865 { 4866 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 4867 { 4868 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 4869 } 4870 l.resize(j.size()); 4871 std::transform(j.begin(), j.end(), std::begin(l), 4872 [](const BasicJsonType & elem) 4873 { 4874 return elem.template get<T>(); 4875 }); 4876 } 4877 4878 template<typename BasicJsonType, typename T, std::size_t N> 4879 auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 4880 -> decltype(j.template get<T>(), void()) 4881 { 4882 for (std::size_t i = 0; i < N; ++i) 4883 { 4884 arr[i] = j.at(i).template get<T>(); 4885 } 4886 } 4887 4888 template<typename BasicJsonType> 4889 inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) 4890 { 4891 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>(); 4892 } 4893 4894 template<typename BasicJsonType, typename T, std::size_t N> 4895 auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, 4896 priority_tag<2> /*unused*/) 4897 -> decltype(j.template get<T>(), void()) 4898 { 4899 for (std::size_t i = 0; i < N; ++i) 4900 { 4901 arr[i] = j.at(i).template get<T>(); 4902 } 4903 } 4904 4905 template<typename BasicJsonType, typename ConstructibleArrayType, 4906 enable_if_t< 4907 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, 4908 int> = 0> 4909 auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) 4910 -> decltype( 4911 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()), 4912 j.template get<typename ConstructibleArrayType::value_type>(), 4913 void()) 4914 { 4915 using std::end; 4916 4917 ConstructibleArrayType ret; 4918 ret.reserve(j.size()); 4919 std::transform(j.begin(), j.end(), 4920 std::inserter(ret, end(ret)), [](const BasicJsonType & i) 4921 { 4922 // get<BasicJsonType>() returns *this, this won't call a from_json 4923 // method when value_type is BasicJsonType 4924 return i.template get<typename ConstructibleArrayType::value_type>(); 4925 }); 4926 arr = std::move(ret); 4927 } 4928 4929 template<typename BasicJsonType, typename ConstructibleArrayType, 4930 enable_if_t< 4931 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, 4932 int> = 0> 4933 inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, 4934 priority_tag<0> /*unused*/) 4935 { 4936 using std::end; 4937 4938 ConstructibleArrayType ret; 4939 std::transform( 4940 j.begin(), j.end(), std::inserter(ret, end(ret)), 4941 [](const BasicJsonType & i) 4942 { 4943 // get<BasicJsonType>() returns *this, this won't call a from_json 4944 // method when value_type is BasicJsonType 4945 return i.template get<typename ConstructibleArrayType::value_type>(); 4946 }); 4947 arr = std::move(ret); 4948 } 4949 4950 template < typename BasicJsonType, typename ConstructibleArrayType, 4951 enable_if_t < 4952 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&& 4953 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&& 4954 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&& 4955 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&& 4956 !is_basic_json<ConstructibleArrayType>::value, 4957 int > = 0 > 4958 auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) 4959 -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), 4960 j.template get<typename ConstructibleArrayType::value_type>(), 4961 void()) 4962 { 4963 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 4964 { 4965 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 4966 } 4967 4968 from_json_array_impl(j, arr, priority_tag<3> {}); 4969 } 4970 4971 template < typename BasicJsonType, typename T, std::size_t... Idx > 4972 std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j, 4973 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/) 4974 { 4975 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } }; 4976 } 4977 4978 template < typename BasicJsonType, typename T, std::size_t N > 4979 auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag) 4980 -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {})) 4981 { 4982 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 4983 { 4984 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 4985 } 4986 4987 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}); 4988 } 4989 4990 template<typename BasicJsonType> 4991 inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) 4992 { 4993 if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) 4994 { 4995 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j)); 4996 } 4997 4998 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>(); 4999 } 5000 5001 template<typename BasicJsonType, typename ConstructibleObjectType, 5002 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0> 5003 inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) 5004 { 5005 if (JSON_HEDLEY_UNLIKELY(!j.is_object())) 5006 { 5007 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j)); 5008 } 5009 5010 ConstructibleObjectType ret; 5011 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>(); 5012 using value_type = typename ConstructibleObjectType::value_type; 5013 std::transform( 5014 inner_object->begin(), inner_object->end(), 5015 std::inserter(ret, ret.begin()), 5016 [](typename BasicJsonType::object_t::value_type const & p) 5017 { 5018 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>()); 5019 }); 5020 obj = std::move(ret); 5021 } 5022 5023 // overload for arithmetic types, not chosen for basic_json template arguments 5024 // (BooleanType, etc..); note: Is it really necessary to provide explicit 5025 // overloads for boolean_t etc. in case of a custom BooleanType which is not 5026 // an arithmetic type? 5027 template < typename BasicJsonType, typename ArithmeticType, 5028 enable_if_t < 5029 std::is_arithmetic<ArithmeticType>::value&& 5030 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&& 5031 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&& 5032 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&& 5033 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, 5034 int > = 0 > 5035 inline void from_json(const BasicJsonType& j, ArithmeticType& val) 5036 { 5037 switch (static_cast<value_t>(j)) 5038 { 5039 case value_t::number_unsigned: 5040 { 5041 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>()); 5042 break; 5043 } 5044 case value_t::number_integer: 5045 { 5046 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>()); 5047 break; 5048 } 5049 case value_t::number_float: 5050 { 5051 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); 5052 break; 5053 } 5054 case value_t::boolean: 5055 { 5056 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>()); 5057 break; 5058 } 5059 5060 case value_t::null: 5061 case value_t::object: 5062 case value_t::array: 5063 case value_t::string: 5064 case value_t::binary: 5065 case value_t::discarded: 5066 default: 5067 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); 5068 } 5069 } 5070 5071 template<typename BasicJsonType, typename... Args, std::size_t... Idx> 5072 std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/) 5073 { 5074 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...); 5075 } 5076 5077 template < typename BasicJsonType, class A1, class A2 > 5078 std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/) 5079 { 5080 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(), 5081 std::forward<BasicJsonType>(j).at(1).template get<A2>()}; 5082 } 5083 5084 template<typename BasicJsonType, typename A1, typename A2> 5085 inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/) 5086 { 5087 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {}); 5088 } 5089 5090 template<typename BasicJsonType, typename... Args> 5091 std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/) 5092 { 5093 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {}); 5094 } 5095 5096 template<typename BasicJsonType, typename... Args> 5097 inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/) 5098 { 5099 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {}); 5100 } 5101 5102 template<typename BasicJsonType, typename TupleRelated> 5103 auto from_json(BasicJsonType&& j, TupleRelated&& t) 5104 -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {})) 5105 { 5106 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 5107 { 5108 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 5109 } 5110 5111 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}); 5112 } 5113 5114 template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, 5115 typename = enable_if_t < !std::is_constructible < 5116 typename BasicJsonType::string_t, Key >::value >> 5117 inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m) 5118 { 5119 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 5120 { 5121 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 5122 } 5123 m.clear(); 5124 for (const auto& p : j) 5125 { 5126 if (JSON_HEDLEY_UNLIKELY(!p.is_array())) 5127 { 5128 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); 5129 } 5130 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>()); 5131 } 5132 } 5133 5134 template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, 5135 typename = enable_if_t < !std::is_constructible < 5136 typename BasicJsonType::string_t, Key >::value >> 5137 inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m) 5138 { 5139 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 5140 { 5141 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 5142 } 5143 m.clear(); 5144 for (const auto& p : j) 5145 { 5146 if (JSON_HEDLEY_UNLIKELY(!p.is_array())) 5147 { 5148 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); 5149 } 5150 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>()); 5151 } 5152 } 5153 5154 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM 5155 template<typename BasicJsonType> 5156 inline void from_json(const BasicJsonType& j, std_fs::path& p) 5157 { 5158 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) 5159 { 5160 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); 5161 } 5162 p = *j.template get_ptr<const typename BasicJsonType::string_t*>(); 5163 } 5164 #endif 5165 5166 struct from_json_fn 5167 { 5168 template<typename BasicJsonType, typename T> 5169 auto operator()(const BasicJsonType& j, T&& val) const 5170 noexcept(noexcept(from_json(j, std::forward<T>(val)))) 5171 -> decltype(from_json(j, std::forward<T>(val))) 5172 { 5173 return from_json(j, std::forward<T>(val)); 5174 } 5175 }; 5176 5177 } // namespace detail 5178 5179 #ifndef JSON_HAS_CPP_17 5180 /// namespace to hold default `from_json` function 5181 /// to see why this is required: 5182 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html 5183 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) 5184 { 5185 #endif 5186 JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers) 5187 detail::static_const<detail::from_json_fn>::value; 5188 #ifndef JSON_HAS_CPP_17 5189 } // namespace 5190 #endif 5191 5192 NLOHMANN_JSON_NAMESPACE_END 5193 5194 // #include <nlohmann/detail/conversions/to_json.hpp> 5195 // __ _____ _____ _____ 5196 // __| | __| | | | JSON for Modern C++ 5197 // | | |__ | | | | | | version 3.11.3 5198 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 5199 // 5200 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 5201 // SPDX-License-Identifier: MIT 5202 5203 5204 5205 #include <algorithm> // copy 5206 #include <iterator> // begin, end 5207 #ifdef JSON_HAS_CPP_17 5208 #include <optional> // optional 5209 #endif 5210 #include <string> // string 5211 #include <tuple> // tuple, get 5212 #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type 5213 #include <utility> // move, forward, declval, pair 5214 #include <valarray> // valarray 5215 #include <vector> // vector 5216 5217 // #include <nlohmann/detail/iterators/iteration_proxy.hpp> 5218 // __ _____ _____ _____ 5219 // __| | __| | | | JSON for Modern C++ 5220 // | | |__ | | | | | | version 3.11.3 5221 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 5222 // 5223 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 5224 // SPDX-License-Identifier: MIT 5225 5226 5227 5228 #include <cstddef> // size_t 5229 #include <iterator> // forward_iterator_tag 5230 #include <string> // string, to_string 5231 #include <tuple> // tuple_size, get, tuple_element 5232 #include <utility> // move 5233 5234 #if JSON_HAS_RANGES 5235 #include <ranges> // enable_borrowed_range 5236 #endif 5237 5238 // #include <nlohmann/detail/abi_macros.hpp> 5239 5240 // #include <nlohmann/detail/meta/type_traits.hpp> 5241 5242 // #include <nlohmann/detail/value_t.hpp> 5243 5244 5245 NLOHMANN_JSON_NAMESPACE_BEGIN 5246 namespace detail 5247 { 5248 5249 template<typename string_type> 5250 void int_to_string( string_type& target, std::size_t value ) 5251 { 5252 // For ADL 5253 using std::to_string; 5254 target = to_string(value); 5255 } 5256 template<typename IteratorType> class iteration_proxy_value 5257 { 5258 public: 5259 using difference_type = std::ptrdiff_t; 5260 using value_type = iteration_proxy_value; 5261 using pointer = value_type *; 5262 using reference = value_type &; 5263 using iterator_category = std::forward_iterator_tag; 5264 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type; 5265 5266 private: 5267 /// the iterator 5268 IteratorType anchor{}; 5269 /// an index for arrays (used to create key names) 5270 std::size_t array_index = 0; 5271 /// last stringified array index 5272 mutable std::size_t array_index_last = 0; 5273 /// a string representation of the array index 5274 mutable string_type array_index_str = "0"; 5275 /// an empty string (to return a reference for primitive values) 5276 string_type empty_str{}; 5277 5278 public: 5279 explicit iteration_proxy_value() = default; 5280 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0) 5281 noexcept(std::is_nothrow_move_constructible<IteratorType>::value 5282 && std::is_nothrow_default_constructible<string_type>::value) 5283 : anchor(std::move(it)) 5284 , array_index(array_index_) 5285 {} 5286 5287 iteration_proxy_value(iteration_proxy_value const&) = default; 5288 iteration_proxy_value& operator=(iteration_proxy_value const&) = default; 5289 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions 5290 iteration_proxy_value(iteration_proxy_value&&) 5291 noexcept(std::is_nothrow_move_constructible<IteratorType>::value 5292 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) 5293 iteration_proxy_value& operator=(iteration_proxy_value&&) 5294 noexcept(std::is_nothrow_move_assignable<IteratorType>::value 5295 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) 5296 ~iteration_proxy_value() = default; 5297 5298 /// dereference operator (needed for range-based for) 5299 const iteration_proxy_value& operator*() const 5300 { 5301 return *this; 5302 } 5303 5304 /// increment operator (needed for range-based for) 5305 iteration_proxy_value& operator++() 5306 { 5307 ++anchor; 5308 ++array_index; 5309 5310 return *this; 5311 } 5312 5313 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp) 5314 { 5315 auto tmp = iteration_proxy_value(anchor, array_index); 5316 ++anchor; 5317 ++array_index; 5318 return tmp; 5319 } 5320 5321 /// equality operator (needed for InputIterator) 5322 bool operator==(const iteration_proxy_value& o) const 5323 { 5324 return anchor == o.anchor; 5325 } 5326 5327 /// inequality operator (needed for range-based for) 5328 bool operator!=(const iteration_proxy_value& o) const 5329 { 5330 return anchor != o.anchor; 5331 } 5332 5333 /// return key of the iterator 5334 const string_type& key() const 5335 { 5336 JSON_ASSERT(anchor.m_object != nullptr); 5337 5338 switch (anchor.m_object->type()) 5339 { 5340 // use integer array index as key 5341 case value_t::array: 5342 { 5343 if (array_index != array_index_last) 5344 { 5345 int_to_string( array_index_str, array_index ); 5346 array_index_last = array_index; 5347 } 5348 return array_index_str; 5349 } 5350 5351 // use key from the object 5352 case value_t::object: 5353 return anchor.key(); 5354 5355 // use an empty key for all primitive types 5356 case value_t::null: 5357 case value_t::string: 5358 case value_t::boolean: 5359 case value_t::number_integer: 5360 case value_t::number_unsigned: 5361 case value_t::number_float: 5362 case value_t::binary: 5363 case value_t::discarded: 5364 default: 5365 return empty_str; 5366 } 5367 } 5368 5369 /// return value of the iterator 5370 typename IteratorType::reference value() const 5371 { 5372 return anchor.value(); 5373 } 5374 }; 5375 5376 /// proxy class for the items() function 5377 template<typename IteratorType> class iteration_proxy 5378 { 5379 private: 5380 /// the container to iterate 5381 typename IteratorType::pointer container = nullptr; 5382 5383 public: 5384 explicit iteration_proxy() = default; 5385 5386 /// construct iteration proxy from a container 5387 explicit iteration_proxy(typename IteratorType::reference cont) noexcept 5388 : container(&cont) {} 5389 5390 iteration_proxy(iteration_proxy const&) = default; 5391 iteration_proxy& operator=(iteration_proxy const&) = default; 5392 iteration_proxy(iteration_proxy&&) noexcept = default; 5393 iteration_proxy& operator=(iteration_proxy&&) noexcept = default; 5394 ~iteration_proxy() = default; 5395 5396 /// return iterator begin (needed for range-based for) 5397 iteration_proxy_value<IteratorType> begin() const noexcept 5398 { 5399 return iteration_proxy_value<IteratorType>(container->begin()); 5400 } 5401 5402 /// return iterator end (needed for range-based for) 5403 iteration_proxy_value<IteratorType> end() const noexcept 5404 { 5405 return iteration_proxy_value<IteratorType>(container->end()); 5406 } 5407 }; 5408 5409 // Structured Bindings Support 5410 // For further reference see https://blog.tartanllama.xyz/structured-bindings/ 5411 // And see https://github.com/nlohmann/json/pull/1391 5412 template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0> 5413 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key()) 5414 { 5415 return i.key(); 5416 } 5417 // Structured Bindings Support 5418 // For further reference see https://blog.tartanllama.xyz/structured-bindings/ 5419 // And see https://github.com/nlohmann/json/pull/1391 5420 template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0> 5421 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value()) 5422 { 5423 return i.value(); 5424 } 5425 5426 } // namespace detail 5427 NLOHMANN_JSON_NAMESPACE_END 5428 5429 // The Addition to the STD Namespace is required to add 5430 // Structured Bindings Support to the iteration_proxy_value class 5431 // For further reference see https://blog.tartanllama.xyz/structured-bindings/ 5432 // And see https://github.com/nlohmann/json/pull/1391 5433 namespace std 5434 { 5435 5436 #if defined(__clang__) 5437 // Fix: https://github.com/nlohmann/json/issues/1401 5438 #pragma clang diagnostic push 5439 #pragma clang diagnostic ignored "-Wmismatched-tags" 5440 #endif 5441 template<typename IteratorType> 5442 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp) 5443 : public std::integral_constant<std::size_t, 2> {}; 5444 5445 template<std::size_t N, typename IteratorType> 5446 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp) 5447 { 5448 public: 5449 using type = decltype( 5450 get<N>(std::declval < 5451 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ())); 5452 }; 5453 #if defined(__clang__) 5454 #pragma clang diagnostic pop 5455 #endif 5456 5457 } // namespace std 5458 5459 #if JSON_HAS_RANGES 5460 template <typename IteratorType> 5461 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true; 5462 #endif 5463 5464 // #include <nlohmann/detail/macro_scope.hpp> 5465 5466 // #include <nlohmann/detail/meta/cpp_future.hpp> 5467 5468 // #include <nlohmann/detail/meta/std_fs.hpp> 5469 5470 // #include <nlohmann/detail/meta/type_traits.hpp> 5471 5472 // #include <nlohmann/detail/value_t.hpp> 5473 5474 5475 NLOHMANN_JSON_NAMESPACE_BEGIN 5476 namespace detail 5477 { 5478 5479 ////////////////// 5480 // constructors // 5481 ////////////////// 5482 5483 /* 5484 * Note all external_constructor<>::construct functions need to call 5485 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an 5486 * allocated value (e.g., a string). See bug issue 5487 * https://github.com/nlohmann/json/issues/2865 for more information. 5488 */ 5489 5490 template<value_t> struct external_constructor; 5491 5492 template<> 5493 struct external_constructor<value_t::boolean> 5494 { 5495 template<typename BasicJsonType> 5496 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept 5497 { 5498 j.m_data.m_value.destroy(j.m_data.m_type); 5499 j.m_data.m_type = value_t::boolean; 5500 j.m_data.m_value = b; 5501 j.assert_invariant(); 5502 } 5503 }; 5504 5505 template<> 5506 struct external_constructor<value_t::string> 5507 { 5508 template<typename BasicJsonType> 5509 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) 5510 { 5511 j.m_data.m_value.destroy(j.m_data.m_type); 5512 j.m_data.m_type = value_t::string; 5513 j.m_data.m_value = s; 5514 j.assert_invariant(); 5515 } 5516 5517 template<typename BasicJsonType> 5518 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) 5519 { 5520 j.m_data.m_value.destroy(j.m_data.m_type); 5521 j.m_data.m_type = value_t::string; 5522 j.m_data.m_value = std::move(s); 5523 j.assert_invariant(); 5524 } 5525 5526 template < typename BasicJsonType, typename CompatibleStringType, 5527 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value, 5528 int > = 0 > 5529 static void construct(BasicJsonType& j, const CompatibleStringType& str) 5530 { 5531 j.m_data.m_value.destroy(j.m_data.m_type); 5532 j.m_data.m_type = value_t::string; 5533 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str); 5534 j.assert_invariant(); 5535 } 5536 }; 5537 5538 template<> 5539 struct external_constructor<value_t::binary> 5540 { 5541 template<typename BasicJsonType> 5542 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) 5543 { 5544 j.m_data.m_value.destroy(j.m_data.m_type); 5545 j.m_data.m_type = value_t::binary; 5546 j.m_data.m_value = typename BasicJsonType::binary_t(b); 5547 j.assert_invariant(); 5548 } 5549 5550 template<typename BasicJsonType> 5551 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) 5552 { 5553 j.m_data.m_value.destroy(j.m_data.m_type); 5554 j.m_data.m_type = value_t::binary; 5555 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b)); 5556 j.assert_invariant(); 5557 } 5558 }; 5559 5560 template<> 5561 struct external_constructor<value_t::number_float> 5562 { 5563 template<typename BasicJsonType> 5564 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept 5565 { 5566 j.m_data.m_value.destroy(j.m_data.m_type); 5567 j.m_data.m_type = value_t::number_float; 5568 j.m_data.m_value = val; 5569 j.assert_invariant(); 5570 } 5571 }; 5572 5573 template<> 5574 struct external_constructor<value_t::number_unsigned> 5575 { 5576 template<typename BasicJsonType> 5577 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept 5578 { 5579 j.m_data.m_value.destroy(j.m_data.m_type); 5580 j.m_data.m_type = value_t::number_unsigned; 5581 j.m_data.m_value = val; 5582 j.assert_invariant(); 5583 } 5584 }; 5585 5586 template<> 5587 struct external_constructor<value_t::number_integer> 5588 { 5589 template<typename BasicJsonType> 5590 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept 5591 { 5592 j.m_data.m_value.destroy(j.m_data.m_type); 5593 j.m_data.m_type = value_t::number_integer; 5594 j.m_data.m_value = val; 5595 j.assert_invariant(); 5596 } 5597 }; 5598 5599 template<> 5600 struct external_constructor<value_t::array> 5601 { 5602 template<typename BasicJsonType> 5603 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) 5604 { 5605 j.m_data.m_value.destroy(j.m_data.m_type); 5606 j.m_data.m_type = value_t::array; 5607 j.m_data.m_value = arr; 5608 j.set_parents(); 5609 j.assert_invariant(); 5610 } 5611 5612 template<typename BasicJsonType> 5613 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) 5614 { 5615 j.m_data.m_value.destroy(j.m_data.m_type); 5616 j.m_data.m_type = value_t::array; 5617 j.m_data.m_value = std::move(arr); 5618 j.set_parents(); 5619 j.assert_invariant(); 5620 } 5621 5622 template < typename BasicJsonType, typename CompatibleArrayType, 5623 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value, 5624 int > = 0 > 5625 static void construct(BasicJsonType& j, const CompatibleArrayType& arr) 5626 { 5627 using std::begin; 5628 using std::end; 5629 5630 j.m_data.m_value.destroy(j.m_data.m_type); 5631 j.m_data.m_type = value_t::array; 5632 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr)); 5633 j.set_parents(); 5634 j.assert_invariant(); 5635 } 5636 5637 template<typename BasicJsonType> 5638 static void construct(BasicJsonType& j, const std::vector<bool>& arr) 5639 { 5640 j.m_data.m_value.destroy(j.m_data.m_type); 5641 j.m_data.m_type = value_t::array; 5642 j.m_data.m_value = value_t::array; 5643 j.m_data.m_value.array->reserve(arr.size()); 5644 for (const bool x : arr) 5645 { 5646 j.m_data.m_value.array->push_back(x); 5647 j.set_parent(j.m_data.m_value.array->back()); 5648 } 5649 j.assert_invariant(); 5650 } 5651 5652 template<typename BasicJsonType, typename T, 5653 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0> 5654 static void construct(BasicJsonType& j, const std::valarray<T>& arr) 5655 { 5656 j.m_data.m_value.destroy(j.m_data.m_type); 5657 j.m_data.m_type = value_t::array; 5658 j.m_data.m_value = value_t::array; 5659 j.m_data.m_value.array->resize(arr.size()); 5660 if (arr.size() > 0) 5661 { 5662 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin()); 5663 } 5664 j.set_parents(); 5665 j.assert_invariant(); 5666 } 5667 }; 5668 5669 template<> 5670 struct external_constructor<value_t::object> 5671 { 5672 template<typename BasicJsonType> 5673 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) 5674 { 5675 j.m_data.m_value.destroy(j.m_data.m_type); 5676 j.m_data.m_type = value_t::object; 5677 j.m_data.m_value = obj; 5678 j.set_parents(); 5679 j.assert_invariant(); 5680 } 5681 5682 template<typename BasicJsonType> 5683 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) 5684 { 5685 j.m_data.m_value.destroy(j.m_data.m_type); 5686 j.m_data.m_type = value_t::object; 5687 j.m_data.m_value = std::move(obj); 5688 j.set_parents(); 5689 j.assert_invariant(); 5690 } 5691 5692 template < typename BasicJsonType, typename CompatibleObjectType, 5693 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 > 5694 static void construct(BasicJsonType& j, const CompatibleObjectType& obj) 5695 { 5696 using std::begin; 5697 using std::end; 5698 5699 j.m_data.m_value.destroy(j.m_data.m_type); 5700 j.m_data.m_type = value_t::object; 5701 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj)); 5702 j.set_parents(); 5703 j.assert_invariant(); 5704 } 5705 }; 5706 5707 ///////////// 5708 // to_json // 5709 ///////////// 5710 5711 #ifdef JSON_HAS_CPP_17 5712 template<typename BasicJsonType, typename T, 5713 enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0> 5714 void to_json(BasicJsonType& j, const std::optional<T>& opt) 5715 { 5716 if (opt.has_value()) 5717 { 5718 j = *opt; 5719 } 5720 else 5721 { 5722 j = nullptr; 5723 } 5724 } 5725 #endif 5726 5727 template<typename BasicJsonType, typename T, 5728 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0> 5729 inline void to_json(BasicJsonType& j, T b) noexcept 5730 { 5731 external_constructor<value_t::boolean>::construct(j, b); 5732 } 5733 5734 template < typename BasicJsonType, typename BoolRef, 5735 enable_if_t < 5736 ((std::is_same<std::vector<bool>::reference, BoolRef>::value 5737 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value) 5738 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value 5739 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>, 5740 typename BasicJsonType::boolean_t >::value)) 5741 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 > 5742 inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept 5743 { 5744 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b)); 5745 } 5746 5747 template<typename BasicJsonType, typename CompatibleString, 5748 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0> 5749 inline void to_json(BasicJsonType& j, const CompatibleString& s) 5750 { 5751 external_constructor<value_t::string>::construct(j, s); 5752 } 5753 5754 template<typename BasicJsonType> 5755 inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) 5756 { 5757 external_constructor<value_t::string>::construct(j, std::move(s)); 5758 } 5759 5760 template<typename BasicJsonType, typename FloatType, 5761 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0> 5762 inline void to_json(BasicJsonType& j, FloatType val) noexcept 5763 { 5764 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val)); 5765 } 5766 5767 template<typename BasicJsonType, typename CompatibleNumberUnsignedType, 5768 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0> 5769 inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept 5770 { 5771 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val)); 5772 } 5773 5774 template<typename BasicJsonType, typename CompatibleNumberIntegerType, 5775 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0> 5776 inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept 5777 { 5778 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val)); 5779 } 5780 5781 #if !JSON_DISABLE_ENUM_SERIALIZATION 5782 template<typename BasicJsonType, typename EnumType, 5783 enable_if_t<std::is_enum<EnumType>::value, int> = 0> 5784 inline void to_json(BasicJsonType& j, EnumType e) noexcept 5785 { 5786 using underlying_type = typename std::underlying_type<EnumType>::type; 5787 static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer; 5788 external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e)); 5789 } 5790 #endif // JSON_DISABLE_ENUM_SERIALIZATION 5791 5792 template<typename BasicJsonType> 5793 inline void to_json(BasicJsonType& j, const std::vector<bool>& e) 5794 { 5795 external_constructor<value_t::array>::construct(j, e); 5796 } 5797 5798 template < typename BasicJsonType, typename CompatibleArrayType, 5799 enable_if_t < is_compatible_array_type<BasicJsonType, 5800 CompatibleArrayType>::value&& 5801 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&& 5802 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&& 5803 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&& 5804 !is_basic_json<CompatibleArrayType>::value, 5805 int > = 0 > 5806 inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr) 5807 { 5808 external_constructor<value_t::array>::construct(j, arr); 5809 } 5810 5811 template<typename BasicJsonType> 5812 inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) 5813 { 5814 external_constructor<value_t::binary>::construct(j, bin); 5815 } 5816 5817 template<typename BasicJsonType, typename T, 5818 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0> 5819 inline void to_json(BasicJsonType& j, const std::valarray<T>& arr) 5820 { 5821 external_constructor<value_t::array>::construct(j, std::move(arr)); 5822 } 5823 5824 template<typename BasicJsonType> 5825 inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) 5826 { 5827 external_constructor<value_t::array>::construct(j, std::move(arr)); 5828 } 5829 5830 template < typename BasicJsonType, typename CompatibleObjectType, 5831 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 > 5832 inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj) 5833 { 5834 external_constructor<value_t::object>::construct(j, obj); 5835 } 5836 5837 template<typename BasicJsonType> 5838 inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) 5839 { 5840 external_constructor<value_t::object>::construct(j, std::move(obj)); 5841 } 5842 5843 template < 5844 typename BasicJsonType, typename T, std::size_t N, 5845 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t, 5846 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 5847 int > = 0 > 5848 inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 5849 { 5850 external_constructor<value_t::array>::construct(j, arr); 5851 } 5852 5853 template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 > 5854 inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p) 5855 { 5856 j = { p.first, p.second }; 5857 } 5858 5859 // for https://github.com/nlohmann/json/pull/1134 5860 template<typename BasicJsonType, typename T, 5861 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0> 5862 inline void to_json(BasicJsonType& j, const T& b) 5863 { 5864 j = { {b.key(), b.value()} }; 5865 } 5866 5867 template<typename BasicJsonType, typename Tuple, std::size_t... Idx> 5868 inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/) 5869 { 5870 j = { std::get<Idx>(t)... }; 5871 } 5872 5873 template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0> 5874 inline void to_json(BasicJsonType& j, const T& t) 5875 { 5876 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {}); 5877 } 5878 5879 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM 5880 template<typename BasicJsonType> 5881 inline void to_json(BasicJsonType& j, const std_fs::path& p) 5882 { 5883 j = p.string(); 5884 } 5885 #endif 5886 5887 struct to_json_fn 5888 { 5889 template<typename BasicJsonType, typename T> 5890 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val)))) 5891 -> decltype(to_json(j, std::forward<T>(val)), void()) 5892 { 5893 return to_json(j, std::forward<T>(val)); 5894 } 5895 }; 5896 } // namespace detail 5897 5898 #ifndef JSON_HAS_CPP_17 5899 /// namespace to hold default `to_json` function 5900 /// to see why this is required: 5901 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html 5902 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) 5903 { 5904 #endif 5905 JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers) 5906 detail::static_const<detail::to_json_fn>::value; 5907 #ifndef JSON_HAS_CPP_17 5908 } // namespace 5909 #endif 5910 5911 NLOHMANN_JSON_NAMESPACE_END 5912 5913 // #include <nlohmann/detail/meta/identity_tag.hpp> 5914 5915 5916 NLOHMANN_JSON_NAMESPACE_BEGIN 5917 5918 /// @sa https://json.nlohmann.me/api/adl_serializer/ 5919 template<typename ValueType, typename> 5920 struct adl_serializer 5921 { 5922 /// @brief convert a JSON value to any value type 5923 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ 5924 template<typename BasicJsonType, typename TargetType = ValueType> 5925 static auto from_json(BasicJsonType && j, TargetType& val) noexcept( 5926 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val))) 5927 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void()) 5928 { 5929 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val); 5930 } 5931 5932 /// @brief convert a JSON value to any value type 5933 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ 5934 template<typename BasicJsonType, typename TargetType = ValueType> 5935 static auto from_json(BasicJsonType && j) noexcept( 5936 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))) 5937 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})) 5938 { 5939 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}); 5940 } 5941 5942 /// @brief convert any value type to a JSON value 5943 /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/ 5944 template<typename BasicJsonType, typename TargetType = ValueType> 5945 static auto to_json(BasicJsonType& j, TargetType && val) noexcept( 5946 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val)))) 5947 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void()) 5948 { 5949 ::nlohmann::to_json(j, std::forward<TargetType>(val)); 5950 } 5951 }; 5952 5953 NLOHMANN_JSON_NAMESPACE_END 5954 5955 // #include <nlohmann/byte_container_with_subtype.hpp> 5956 // __ _____ _____ _____ 5957 // __| | __| | | | JSON for Modern C++ 5958 // | | |__ | | | | | | version 3.11.3 5959 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 5960 // 5961 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 5962 // SPDX-License-Identifier: MIT 5963 5964 5965 5966 #include <cstdint> // uint8_t, uint64_t 5967 #include <tuple> // tie 5968 #include <utility> // move 5969 5970 // #include <nlohmann/detail/abi_macros.hpp> 5971 5972 5973 NLOHMANN_JSON_NAMESPACE_BEGIN 5974 5975 /// @brief an internal type for a backed binary type 5976 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/ 5977 template<typename BinaryType> 5978 class byte_container_with_subtype : public BinaryType 5979 { 5980 public: 5981 using container_type = BinaryType; 5982 using subtype_type = std::uint64_t; 5983 5984 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 5985 byte_container_with_subtype() noexcept(noexcept(container_type())) 5986 : container_type() 5987 {} 5988 5989 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 5990 byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b))) 5991 : container_type(b) 5992 {} 5993 5994 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 5995 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b)))) 5996 : container_type(std::move(b)) 5997 {} 5998 5999 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 6000 byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b))) 6001 : container_type(b) 6002 , m_subtype(subtype_) 6003 , m_has_subtype(true) 6004 {} 6005 6006 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 6007 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b)))) 6008 : container_type(std::move(b)) 6009 , m_subtype(subtype_) 6010 , m_has_subtype(true) 6011 {} 6012 6013 bool operator==(const byte_container_with_subtype& rhs) const 6014 { 6015 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) == 6016 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype); 6017 } 6018 6019 bool operator!=(const byte_container_with_subtype& rhs) const 6020 { 6021 return !(rhs == *this); 6022 } 6023 6024 /// @brief sets the binary subtype 6025 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/ 6026 void set_subtype(subtype_type subtype_) noexcept 6027 { 6028 m_subtype = subtype_; 6029 m_has_subtype = true; 6030 } 6031 6032 /// @brief return the binary subtype 6033 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/ 6034 constexpr subtype_type subtype() const noexcept 6035 { 6036 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1); 6037 } 6038 6039 /// @brief return whether the value has a subtype 6040 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/ 6041 constexpr bool has_subtype() const noexcept 6042 { 6043 return m_has_subtype; 6044 } 6045 6046 /// @brief clears the binary subtype 6047 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/ 6048 void clear_subtype() noexcept 6049 { 6050 m_subtype = 0; 6051 m_has_subtype = false; 6052 } 6053 6054 private: 6055 subtype_type m_subtype = 0; 6056 bool m_has_subtype = false; 6057 }; 6058 6059 NLOHMANN_JSON_NAMESPACE_END 6060 6061 // #include <nlohmann/detail/conversions/from_json.hpp> 6062 6063 // #include <nlohmann/detail/conversions/to_json.hpp> 6064 6065 // #include <nlohmann/detail/exceptions.hpp> 6066 6067 // #include <nlohmann/detail/hash.hpp> 6068 // __ _____ _____ _____ 6069 // __| | __| | | | JSON for Modern C++ 6070 // | | |__ | | | | | | version 3.11.3 6071 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 6072 // 6073 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 6074 // SPDX-License-Identifier: MIT 6075 6076 6077 6078 #include <cstdint> // uint8_t 6079 #include <cstddef> // size_t 6080 #include <functional> // hash 6081 6082 // #include <nlohmann/detail/abi_macros.hpp> 6083 6084 // #include <nlohmann/detail/value_t.hpp> 6085 6086 6087 NLOHMANN_JSON_NAMESPACE_BEGIN 6088 namespace detail 6089 { 6090 6091 // boost::hash_combine 6092 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept 6093 { 6094 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U); 6095 return seed; 6096 } 6097 6098 /*! 6099 @brief hash a JSON value 6100 6101 The hash function tries to rely on std::hash where possible. Furthermore, the 6102 type of the JSON value is taken into account to have different hash values for 6103 null, 0, 0U, and false, etc. 6104 6105 @tparam BasicJsonType basic_json specialization 6106 @param j JSON value to hash 6107 @return hash value of j 6108 */ 6109 template<typename BasicJsonType> 6110 std::size_t hash(const BasicJsonType& j) 6111 { 6112 using string_t = typename BasicJsonType::string_t; 6113 using number_integer_t = typename BasicJsonType::number_integer_t; 6114 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 6115 using number_float_t = typename BasicJsonType::number_float_t; 6116 6117 const auto type = static_cast<std::size_t>(j.type()); 6118 switch (j.type()) 6119 { 6120 case BasicJsonType::value_t::null: 6121 case BasicJsonType::value_t::discarded: 6122 { 6123 return combine(type, 0); 6124 } 6125 6126 case BasicJsonType::value_t::object: 6127 { 6128 auto seed = combine(type, j.size()); 6129 for (const auto& element : j.items()) 6130 { 6131 const auto h = std::hash<string_t> {}(element.key()); 6132 seed = combine(seed, h); 6133 seed = combine(seed, hash(element.value())); 6134 } 6135 return seed; 6136 } 6137 6138 case BasicJsonType::value_t::array: 6139 { 6140 auto seed = combine(type, j.size()); 6141 for (const auto& element : j) 6142 { 6143 seed = combine(seed, hash(element)); 6144 } 6145 return seed; 6146 } 6147 6148 case BasicJsonType::value_t::string: 6149 { 6150 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>()); 6151 return combine(type, h); 6152 } 6153 6154 case BasicJsonType::value_t::boolean: 6155 { 6156 const auto h = std::hash<bool> {}(j.template get<bool>()); 6157 return combine(type, h); 6158 } 6159 6160 case BasicJsonType::value_t::number_integer: 6161 { 6162 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>()); 6163 return combine(type, h); 6164 } 6165 6166 case BasicJsonType::value_t::number_unsigned: 6167 { 6168 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>()); 6169 return combine(type, h); 6170 } 6171 6172 case BasicJsonType::value_t::number_float: 6173 { 6174 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>()); 6175 return combine(type, h); 6176 } 6177 6178 case BasicJsonType::value_t::binary: 6179 { 6180 auto seed = combine(type, j.get_binary().size()); 6181 const auto h = std::hash<bool> {}(j.get_binary().has_subtype()); 6182 seed = combine(seed, h); 6183 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype())); 6184 for (const auto byte : j.get_binary()) 6185 { 6186 seed = combine(seed, std::hash<std::uint8_t> {}(byte)); 6187 } 6188 return seed; 6189 } 6190 6191 default: // LCOV_EXCL_LINE 6192 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 6193 return 0; // LCOV_EXCL_LINE 6194 } 6195 } 6196 6197 } // namespace detail 6198 NLOHMANN_JSON_NAMESPACE_END 6199 6200 // #include <nlohmann/detail/input/binary_reader.hpp> 6201 // __ _____ _____ _____ 6202 // __| | __| | | | JSON for Modern C++ 6203 // | | |__ | | | | | | version 3.11.3 6204 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 6205 // 6206 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 6207 // SPDX-License-Identifier: MIT 6208 6209 6210 6211 #include <algorithm> // generate_n 6212 #include <array> // array 6213 #include <cmath> // ldexp 6214 #include <cstddef> // size_t 6215 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t 6216 #include <cstdio> // snprintf 6217 #include <cstring> // memcpy 6218 #include <iterator> // back_inserter 6219 #include <limits> // numeric_limits 6220 #include <string> // char_traits, string 6221 #include <utility> // make_pair, move 6222 #include <vector> // vector 6223 #ifdef __cpp_lib_byteswap 6224 #include <bit> //byteswap 6225 #endif 6226 6227 // #include <nlohmann/detail/exceptions.hpp> 6228 6229 // #include <nlohmann/detail/input/input_adapters.hpp> 6230 // __ _____ _____ _____ 6231 // __| | __| | | | JSON for Modern C++ 6232 // | | |__ | | | | | | version 3.11.3 6233 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 6234 // 6235 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 6236 // SPDX-License-Identifier: MIT 6237 6238 6239 6240 #include <array> // array 6241 #include <cstddef> // size_t 6242 #include <cstring> // strlen 6243 #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next 6244 #include <memory> // shared_ptr, make_shared, addressof 6245 #include <numeric> // accumulate 6246 #include <string> // string, char_traits 6247 #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer 6248 #include <utility> // pair, declval 6249 6250 #ifndef JSON_NO_IO 6251 #include <cstdio> // FILE * 6252 #include <istream> // istream 6253 #endif // JSON_NO_IO 6254 6255 // #include <nlohmann/detail/exceptions.hpp> 6256 6257 // #include <nlohmann/detail/iterators/iterator_traits.hpp> 6258 6259 // #include <nlohmann/detail/macro_scope.hpp> 6260 6261 // #include <nlohmann/detail/meta/type_traits.hpp> 6262 6263 6264 NLOHMANN_JSON_NAMESPACE_BEGIN 6265 namespace detail 6266 { 6267 6268 /// the supported input formats 6269 enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata }; 6270 6271 //////////////////// 6272 // input adapters // 6273 //////////////////// 6274 6275 #ifndef JSON_NO_IO 6276 /*! 6277 Input adapter for stdio file access. This adapter read only 1 byte and do not use any 6278 buffer. This adapter is a very low level adapter. 6279 */ 6280 class file_input_adapter 6281 { 6282 public: 6283 using char_type = char; 6284 6285 JSON_HEDLEY_NON_NULL(2) 6286 explicit file_input_adapter(std::FILE* f) noexcept 6287 : m_file(f) 6288 { 6289 JSON_ASSERT(m_file != nullptr); 6290 } 6291 6292 // make class move-only 6293 file_input_adapter(const file_input_adapter&) = delete; 6294 file_input_adapter(file_input_adapter&&) noexcept = default; 6295 file_input_adapter& operator=(const file_input_adapter&) = delete; 6296 file_input_adapter& operator=(file_input_adapter&&) = delete; 6297 ~file_input_adapter() = default; 6298 6299 std::char_traits<char>::int_type get_character() noexcept 6300 { 6301 return std::fgetc(m_file); 6302 } 6303 6304 // returns the number of characters successfully read 6305 template<class T> 6306 std::size_t get_elements(T* dest, std::size_t count = 1) 6307 { 6308 return fread(dest, 1, sizeof(T) * count, m_file); 6309 } 6310 6311 private: 6312 /// the file pointer to read from 6313 std::FILE* m_file; 6314 }; 6315 6316 /*! 6317 Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at 6318 beginning of input. Does not support changing the underlying std::streambuf 6319 in mid-input. Maintains underlying std::istream and std::streambuf to support 6320 subsequent use of standard std::istream operations to process any input 6321 characters following those used in parsing the JSON input. Clears the 6322 std::istream flags; any input errors (e.g., EOF) will be detected by the first 6323 subsequent call for input from the std::istream. 6324 */ 6325 class input_stream_adapter 6326 { 6327 public: 6328 using char_type = char; 6329 6330 ~input_stream_adapter() 6331 { 6332 // clear stream flags; we use underlying streambuf I/O, do not 6333 // maintain ifstream flags, except eof 6334 if (is != nullptr) 6335 { 6336 is->clear(is->rdstate() & std::ios::eofbit); 6337 } 6338 } 6339 6340 explicit input_stream_adapter(std::istream& i) 6341 : is(&i), sb(i.rdbuf()) 6342 {} 6343 6344 // delete because of pointer members 6345 input_stream_adapter(const input_stream_adapter&) = delete; 6346 input_stream_adapter& operator=(input_stream_adapter&) = delete; 6347 input_stream_adapter& operator=(input_stream_adapter&&) = delete; 6348 6349 input_stream_adapter(input_stream_adapter&& rhs) noexcept 6350 : is(rhs.is), sb(rhs.sb) 6351 { 6352 rhs.is = nullptr; 6353 rhs.sb = nullptr; 6354 } 6355 6356 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to 6357 // ensure that std::char_traits<char>::eof() and the character 0xFF do not 6358 // end up as the same value, e.g. 0xFFFFFFFF. 6359 std::char_traits<char>::int_type get_character() 6360 { 6361 auto res = sb->sbumpc(); 6362 // set eof manually, as we don't use the istream interface. 6363 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof())) 6364 { 6365 is->clear(is->rdstate() | std::ios::eofbit); 6366 } 6367 return res; 6368 } 6369 6370 template<class T> 6371 std::size_t get_elements(T* dest, std::size_t count = 1) 6372 { 6373 auto res = static_cast<std::size_t>(sb->sgetn(reinterpret_cast<char*>(dest), static_cast<std::streamsize>(count * sizeof(T)))); 6374 if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T))) 6375 { 6376 is->clear(is->rdstate() | std::ios::eofbit); 6377 } 6378 return res; 6379 } 6380 6381 private: 6382 /// the associated input stream 6383 std::istream* is = nullptr; 6384 std::streambuf* sb = nullptr; 6385 }; 6386 #endif // JSON_NO_IO 6387 6388 // General-purpose iterator-based adapter. It might not be as fast as 6389 // theoretically possible for some containers, but it is extremely versatile. 6390 template<typename IteratorType> 6391 class iterator_input_adapter 6392 { 6393 public: 6394 using char_type = typename std::iterator_traits<IteratorType>::value_type; 6395 6396 iterator_input_adapter(IteratorType first, IteratorType last) 6397 : current(std::move(first)), end(std::move(last)) 6398 {} 6399 6400 typename char_traits<char_type>::int_type get_character() 6401 { 6402 if (JSON_HEDLEY_LIKELY(current != end)) 6403 { 6404 auto result = char_traits<char_type>::to_int_type(*current); 6405 std::advance(current, 1); 6406 return result; 6407 } 6408 6409 return char_traits<char_type>::eof(); 6410 } 6411 6412 // for general iterators, we cannot really do something better than falling back to processing the range one-by-one 6413 template<class T> 6414 std::size_t get_elements(T* dest, std::size_t count = 1) 6415 { 6416 auto* ptr = reinterpret_cast<char*>(dest); 6417 for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index) 6418 { 6419 if (JSON_HEDLEY_LIKELY(current != end)) 6420 { 6421 ptr[read_index] = static_cast<char>(*current); 6422 std::advance(current, 1); 6423 } 6424 else 6425 { 6426 return read_index; 6427 } 6428 } 6429 return count * sizeof(T); 6430 } 6431 6432 private: 6433 IteratorType current; 6434 IteratorType end; 6435 6436 template<typename BaseInputAdapter, size_t T> 6437 friend struct wide_string_input_helper; 6438 6439 bool empty() const 6440 { 6441 return current == end; 6442 } 6443 }; 6444 6445 template<typename BaseInputAdapter, size_t T> 6446 struct wide_string_input_helper; 6447 6448 template<typename BaseInputAdapter> 6449 struct wide_string_input_helper<BaseInputAdapter, 4> 6450 { 6451 // UTF-32 6452 static void fill_buffer(BaseInputAdapter& input, 6453 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, 6454 size_t& utf8_bytes_index, 6455 size_t& utf8_bytes_filled) 6456 { 6457 utf8_bytes_index = 0; 6458 6459 if (JSON_HEDLEY_UNLIKELY(input.empty())) 6460 { 6461 utf8_bytes[0] = std::char_traits<char>::eof(); 6462 utf8_bytes_filled = 1; 6463 } 6464 else 6465 { 6466 // get the current character 6467 const auto wc = input.get_character(); 6468 6469 // UTF-32 to UTF-8 encoding 6470 if (wc < 0x80) 6471 { 6472 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); 6473 utf8_bytes_filled = 1; 6474 } 6475 else if (wc <= 0x7FF) 6476 { 6477 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu)); 6478 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); 6479 utf8_bytes_filled = 2; 6480 } 6481 else if (wc <= 0xFFFF) 6482 { 6483 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu)); 6484 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); 6485 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); 6486 utf8_bytes_filled = 3; 6487 } 6488 else if (wc <= 0x10FFFF) 6489 { 6490 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u)); 6491 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu)); 6492 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); 6493 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); 6494 utf8_bytes_filled = 4; 6495 } 6496 else 6497 { 6498 // unknown character 6499 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); 6500 utf8_bytes_filled = 1; 6501 } 6502 } 6503 } 6504 }; 6505 6506 template<typename BaseInputAdapter> 6507 struct wide_string_input_helper<BaseInputAdapter, 2> 6508 { 6509 // UTF-16 6510 static void fill_buffer(BaseInputAdapter& input, 6511 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, 6512 size_t& utf8_bytes_index, 6513 size_t& utf8_bytes_filled) 6514 { 6515 utf8_bytes_index = 0; 6516 6517 if (JSON_HEDLEY_UNLIKELY(input.empty())) 6518 { 6519 utf8_bytes[0] = std::char_traits<char>::eof(); 6520 utf8_bytes_filled = 1; 6521 } 6522 else 6523 { 6524 // get the current character 6525 const auto wc = input.get_character(); 6526 6527 // UTF-16 to UTF-8 encoding 6528 if (wc < 0x80) 6529 { 6530 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); 6531 utf8_bytes_filled = 1; 6532 } 6533 else if (wc <= 0x7FF) 6534 { 6535 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u))); 6536 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); 6537 utf8_bytes_filled = 2; 6538 } 6539 else if (0xD800 > wc || wc >= 0xE000) 6540 { 6541 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u))); 6542 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); 6543 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); 6544 utf8_bytes_filled = 3; 6545 } 6546 else 6547 { 6548 if (JSON_HEDLEY_UNLIKELY(!input.empty())) 6549 { 6550 const auto wc2 = static_cast<unsigned int>(input.get_character()); 6551 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); 6552 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u)); 6553 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); 6554 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); 6555 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu)); 6556 utf8_bytes_filled = 4; 6557 } 6558 else 6559 { 6560 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); 6561 utf8_bytes_filled = 1; 6562 } 6563 } 6564 } 6565 } 6566 }; 6567 6568 // Wraps another input adapter to convert wide character types into individual bytes. 6569 template<typename BaseInputAdapter, typename WideCharType> 6570 class wide_string_input_adapter 6571 { 6572 public: 6573 using char_type = char; 6574 6575 wide_string_input_adapter(BaseInputAdapter base) 6576 : base_adapter(base) {} 6577 6578 typename std::char_traits<char>::int_type get_character() noexcept 6579 { 6580 // check if buffer needs to be filled 6581 if (utf8_bytes_index == utf8_bytes_filled) 6582 { 6583 fill_buffer<sizeof(WideCharType)>(); 6584 6585 JSON_ASSERT(utf8_bytes_filled > 0); 6586 JSON_ASSERT(utf8_bytes_index == 0); 6587 } 6588 6589 // use buffer 6590 JSON_ASSERT(utf8_bytes_filled > 0); 6591 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled); 6592 return utf8_bytes[utf8_bytes_index++]; 6593 } 6594 6595 // parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here 6596 template<class T> 6597 std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1) 6598 { 6599 JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr)); 6600 } 6601 6602 private: 6603 BaseInputAdapter base_adapter; 6604 6605 template<size_t T> 6606 void fill_buffer() 6607 { 6608 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); 6609 } 6610 6611 /// a buffer for UTF-8 bytes 6612 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; 6613 6614 /// index to the utf8_codes array for the next valid byte 6615 std::size_t utf8_bytes_index = 0; 6616 /// number of valid bytes in the utf8_codes array 6617 std::size_t utf8_bytes_filled = 0; 6618 }; 6619 6620 template<typename IteratorType, typename Enable = void> 6621 struct iterator_input_adapter_factory 6622 { 6623 using iterator_type = IteratorType; 6624 using char_type = typename std::iterator_traits<iterator_type>::value_type; 6625 using adapter_type = iterator_input_adapter<iterator_type>; 6626 6627 static adapter_type create(IteratorType first, IteratorType last) 6628 { 6629 return adapter_type(std::move(first), std::move(last)); 6630 } 6631 }; 6632 6633 template<typename T> 6634 struct is_iterator_of_multibyte 6635 { 6636 using value_type = typename std::iterator_traits<T>::value_type; 6637 enum 6638 { 6639 value = sizeof(value_type) > 1 6640 }; 6641 }; 6642 6643 template<typename IteratorType> 6644 struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>> 6645 { 6646 using iterator_type = IteratorType; 6647 using char_type = typename std::iterator_traits<iterator_type>::value_type; 6648 using base_adapter_type = iterator_input_adapter<iterator_type>; 6649 using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>; 6650 6651 static adapter_type create(IteratorType first, IteratorType last) 6652 { 6653 return adapter_type(base_adapter_type(std::move(first), std::move(last))); 6654 } 6655 }; 6656 6657 // General purpose iterator-based input 6658 template<typename IteratorType> 6659 typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last) 6660 { 6661 using factory_type = iterator_input_adapter_factory<IteratorType>; 6662 return factory_type::create(first, last); 6663 } 6664 6665 // Convenience shorthand from container to iterator 6666 // Enables ADL on begin(container) and end(container) 6667 // Encloses the using declarations in namespace for not to leak them to outside scope 6668 6669 namespace container_input_adapter_factory_impl 6670 { 6671 6672 using std::begin; 6673 using std::end; 6674 6675 template<typename ContainerType, typename Enable = void> 6676 struct container_input_adapter_factory {}; 6677 6678 template<typename ContainerType> 6679 struct container_input_adapter_factory< ContainerType, 6680 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>> 6681 { 6682 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))); 6683 6684 static adapter_type create(const ContainerType& container) 6685 { 6686 return input_adapter(begin(container), end(container)); 6687 } 6688 }; 6689 6690 } // namespace container_input_adapter_factory_impl 6691 6692 template<typename ContainerType> 6693 typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container) 6694 { 6695 return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container); 6696 } 6697 6698 #ifndef JSON_NO_IO 6699 // Special cases with fast paths 6700 inline file_input_adapter input_adapter(std::FILE* file) 6701 { 6702 if (file == nullptr) 6703 { 6704 JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr)); 6705 } 6706 return file_input_adapter(file); 6707 } 6708 6709 inline input_stream_adapter input_adapter(std::istream& stream) 6710 { 6711 return input_stream_adapter(stream); 6712 } 6713 6714 inline input_stream_adapter input_adapter(std::istream&& stream) 6715 { 6716 return input_stream_adapter(stream); 6717 } 6718 #endif // JSON_NO_IO 6719 6720 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>())); 6721 6722 // Null-delimited strings, and the like. 6723 template < typename CharT, 6724 typename std::enable_if < 6725 std::is_pointer<CharT>::value&& 6726 !std::is_array<CharT>::value&& 6727 std::is_integral<typename std::remove_pointer<CharT>::type>::value&& 6728 sizeof(typename std::remove_pointer<CharT>::type) == 1, 6729 int >::type = 0 > 6730 contiguous_bytes_input_adapter input_adapter(CharT b) 6731 { 6732 if (b == nullptr) 6733 { 6734 JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr)); 6735 } 6736 auto length = std::strlen(reinterpret_cast<const char*>(b)); 6737 const auto* ptr = reinterpret_cast<const char*>(b); 6738 return input_adapter(ptr, ptr + length); 6739 } 6740 6741 template<typename T, std::size_t N> 6742 auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 6743 { 6744 return input_adapter(array, array + N); 6745 } 6746 6747 // This class only handles inputs of input_buffer_adapter type. 6748 // It's required so that expressions like {ptr, len} can be implicitly cast 6749 // to the correct adapter. 6750 class span_input_adapter 6751 { 6752 public: 6753 template < typename CharT, 6754 typename std::enable_if < 6755 std::is_pointer<CharT>::value&& 6756 std::is_integral<typename std::remove_pointer<CharT>::type>::value&& 6757 sizeof(typename std::remove_pointer<CharT>::type) == 1, 6758 int >::type = 0 > 6759 span_input_adapter(CharT b, std::size_t l) 6760 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {} 6761 6762 template<class IteratorType, 6763 typename std::enable_if< 6764 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value, 6765 int>::type = 0> 6766 span_input_adapter(IteratorType first, IteratorType last) 6767 : ia(input_adapter(first, last)) {} 6768 6769 contiguous_bytes_input_adapter&& get() 6770 { 6771 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg) 6772 } 6773 6774 private: 6775 contiguous_bytes_input_adapter ia; 6776 }; 6777 6778 } // namespace detail 6779 NLOHMANN_JSON_NAMESPACE_END 6780 6781 // #include <nlohmann/detail/input/json_sax.hpp> 6782 // __ _____ _____ _____ 6783 // __| | __| | | | JSON for Modern C++ 6784 // | | |__ | | | | | | version 3.11.3 6785 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 6786 // 6787 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 6788 // SPDX-License-Identifier: MIT 6789 6790 6791 6792 #include <cstddef> 6793 #include <string> // string 6794 #include <utility> // move 6795 #include <vector> // vector 6796 6797 // #include <nlohmann/detail/exceptions.hpp> 6798 6799 // #include <nlohmann/detail/macro_scope.hpp> 6800 6801 // #include <nlohmann/detail/string_concat.hpp> 6802 6803 6804 NLOHMANN_JSON_NAMESPACE_BEGIN 6805 6806 /*! 6807 @brief SAX interface 6808 6809 This class describes the SAX interface used by @ref nlohmann::json::sax_parse. 6810 Each function is called in different situations while the input is parsed. The 6811 boolean return value informs the parser whether to continue processing the 6812 input. 6813 */ 6814 template<typename BasicJsonType> 6815 struct json_sax 6816 { 6817 using number_integer_t = typename BasicJsonType::number_integer_t; 6818 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 6819 using number_float_t = typename BasicJsonType::number_float_t; 6820 using string_t = typename BasicJsonType::string_t; 6821 using binary_t = typename BasicJsonType::binary_t; 6822 6823 /*! 6824 @brief a null value was read 6825 @return whether parsing should proceed 6826 */ 6827 virtual bool null() = 0; 6828 6829 /*! 6830 @brief a boolean value was read 6831 @param[in] val boolean value 6832 @return whether parsing should proceed 6833 */ 6834 virtual bool boolean(bool val) = 0; 6835 6836 /*! 6837 @brief an integer number was read 6838 @param[in] val integer value 6839 @return whether parsing should proceed 6840 */ 6841 virtual bool number_integer(number_integer_t val) = 0; 6842 6843 /*! 6844 @brief an unsigned integer number was read 6845 @param[in] val unsigned integer value 6846 @return whether parsing should proceed 6847 */ 6848 virtual bool number_unsigned(number_unsigned_t val) = 0; 6849 6850 /*! 6851 @brief a floating-point number was read 6852 @param[in] val floating-point value 6853 @param[in] s raw token value 6854 @return whether parsing should proceed 6855 */ 6856 virtual bool number_float(number_float_t val, const string_t& s) = 0; 6857 6858 /*! 6859 @brief a string value was read 6860 @param[in] val string value 6861 @return whether parsing should proceed 6862 @note It is safe to move the passed string value. 6863 */ 6864 virtual bool string(string_t& val) = 0; 6865 6866 /*! 6867 @brief a binary value was read 6868 @param[in] val binary value 6869 @return whether parsing should proceed 6870 @note It is safe to move the passed binary value. 6871 */ 6872 virtual bool binary(binary_t& val) = 0; 6873 6874 /*! 6875 @brief the beginning of an object was read 6876 @param[in] elements number of object elements or -1 if unknown 6877 @return whether parsing should proceed 6878 @note binary formats may report the number of elements 6879 */ 6880 virtual bool start_object(std::size_t elements) = 0; 6881 6882 /*! 6883 @brief an object key was read 6884 @param[in] val object key 6885 @return whether parsing should proceed 6886 @note It is safe to move the passed string. 6887 */ 6888 virtual bool key(string_t& val) = 0; 6889 6890 /*! 6891 @brief the end of an object was read 6892 @return whether parsing should proceed 6893 */ 6894 virtual bool end_object() = 0; 6895 6896 /*! 6897 @brief the beginning of an array was read 6898 @param[in] elements number of array elements or -1 if unknown 6899 @return whether parsing should proceed 6900 @note binary formats may report the number of elements 6901 */ 6902 virtual bool start_array(std::size_t elements) = 0; 6903 6904 /*! 6905 @brief the end of an array was read 6906 @return whether parsing should proceed 6907 */ 6908 virtual bool end_array() = 0; 6909 6910 /*! 6911 @brief a parse error occurred 6912 @param[in] position the position in the input where the error occurs 6913 @param[in] last_token the last read token 6914 @param[in] ex an exception object describing the error 6915 @return whether parsing should proceed (must return false) 6916 */ 6917 virtual bool parse_error(std::size_t position, 6918 const std::string& last_token, 6919 const detail::exception& ex) = 0; 6920 6921 json_sax() = default; 6922 json_sax(const json_sax&) = default; 6923 json_sax(json_sax&&) noexcept = default; 6924 json_sax& operator=(const json_sax&) = default; 6925 json_sax& operator=(json_sax&&) noexcept = default; 6926 virtual ~json_sax() = default; 6927 }; 6928 6929 namespace detail 6930 { 6931 /*! 6932 @brief SAX implementation to create a JSON value from SAX events 6933 6934 This class implements the @ref json_sax interface and processes the SAX events 6935 to create a JSON value which makes it basically a DOM parser. The structure or 6936 hierarchy of the JSON value is managed by the stack `ref_stack` which contains 6937 a pointer to the respective array or object for each recursion depth. 6938 6939 After successful parsing, the value that is passed by reference to the 6940 constructor contains the parsed value. 6941 6942 @tparam BasicJsonType the JSON type 6943 */ 6944 template<typename BasicJsonType> 6945 class json_sax_dom_parser 6946 { 6947 public: 6948 using number_integer_t = typename BasicJsonType::number_integer_t; 6949 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 6950 using number_float_t = typename BasicJsonType::number_float_t; 6951 using string_t = typename BasicJsonType::string_t; 6952 using binary_t = typename BasicJsonType::binary_t; 6953 6954 /*! 6955 @param[in,out] r reference to a JSON value that is manipulated while 6956 parsing 6957 @param[in] allow_exceptions_ whether parse errors yield exceptions 6958 */ 6959 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) 6960 : root(r), allow_exceptions(allow_exceptions_) 6961 {} 6962 6963 // make class move-only 6964 json_sax_dom_parser(const json_sax_dom_parser&) = delete; 6965 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 6966 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; 6967 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 6968 ~json_sax_dom_parser() = default; 6969 6970 bool null() 6971 { 6972 handle_value(nullptr); 6973 return true; 6974 } 6975 6976 bool boolean(bool val) 6977 { 6978 handle_value(val); 6979 return true; 6980 } 6981 6982 bool number_integer(number_integer_t val) 6983 { 6984 handle_value(val); 6985 return true; 6986 } 6987 6988 bool number_unsigned(number_unsigned_t val) 6989 { 6990 handle_value(val); 6991 return true; 6992 } 6993 6994 bool number_float(number_float_t val, const string_t& /*unused*/) 6995 { 6996 handle_value(val); 6997 return true; 6998 } 6999 7000 bool string(string_t& val) 7001 { 7002 handle_value(val); 7003 return true; 7004 } 7005 7006 bool binary(binary_t& val) 7007 { 7008 handle_value(std::move(val)); 7009 return true; 7010 } 7011 7012 bool start_object(std::size_t len) 7013 { 7014 ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); 7015 7016 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) 7017 { 7018 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); 7019 } 7020 7021 return true; 7022 } 7023 7024 bool key(string_t& val) 7025 { 7026 JSON_ASSERT(!ref_stack.empty()); 7027 JSON_ASSERT(ref_stack.back()->is_object()); 7028 7029 // add null at given key and store the reference for later 7030 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val)); 7031 return true; 7032 } 7033 7034 bool end_object() 7035 { 7036 JSON_ASSERT(!ref_stack.empty()); 7037 JSON_ASSERT(ref_stack.back()->is_object()); 7038 7039 ref_stack.back()->set_parents(); 7040 ref_stack.pop_back(); 7041 return true; 7042 } 7043 7044 bool start_array(std::size_t len) 7045 { 7046 ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); 7047 7048 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) 7049 { 7050 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); 7051 } 7052 7053 return true; 7054 } 7055 7056 bool end_array() 7057 { 7058 JSON_ASSERT(!ref_stack.empty()); 7059 JSON_ASSERT(ref_stack.back()->is_array()); 7060 7061 ref_stack.back()->set_parents(); 7062 ref_stack.pop_back(); 7063 return true; 7064 } 7065 7066 template<class Exception> 7067 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, 7068 const Exception& ex) 7069 { 7070 errored = true; 7071 static_cast<void>(ex); 7072 if (allow_exceptions) 7073 { 7074 JSON_THROW(ex); 7075 } 7076 return false; 7077 } 7078 7079 constexpr bool is_errored() const 7080 { 7081 return errored; 7082 } 7083 7084 private: 7085 /*! 7086 @invariant If the ref stack is empty, then the passed value will be the new 7087 root. 7088 @invariant If the ref stack contains a value, then it is an array or an 7089 object to which we can add elements 7090 */ 7091 template<typename Value> 7092 JSON_HEDLEY_RETURNS_NON_NULL 7093 BasicJsonType* handle_value(Value&& v) 7094 { 7095 if (ref_stack.empty()) 7096 { 7097 root = BasicJsonType(std::forward<Value>(v)); 7098 return &root; 7099 } 7100 7101 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); 7102 7103 if (ref_stack.back()->is_array()) 7104 { 7105 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v)); 7106 return &(ref_stack.back()->m_data.m_value.array->back()); 7107 } 7108 7109 JSON_ASSERT(ref_stack.back()->is_object()); 7110 JSON_ASSERT(object_element); 7111 *object_element = BasicJsonType(std::forward<Value>(v)); 7112 return object_element; 7113 } 7114 7115 /// the parsed JSON value 7116 BasicJsonType& root; 7117 /// stack to model hierarchy of values 7118 std::vector<BasicJsonType*> ref_stack {}; 7119 /// helper to hold the reference for the next object element 7120 BasicJsonType* object_element = nullptr; 7121 /// whether a syntax error occurred 7122 bool errored = false; 7123 /// whether to throw exceptions in case of errors 7124 const bool allow_exceptions = true; 7125 }; 7126 7127 template<typename BasicJsonType> 7128 class json_sax_dom_callback_parser 7129 { 7130 public: 7131 using number_integer_t = typename BasicJsonType::number_integer_t; 7132 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 7133 using number_float_t = typename BasicJsonType::number_float_t; 7134 using string_t = typename BasicJsonType::string_t; 7135 using binary_t = typename BasicJsonType::binary_t; 7136 using parser_callback_t = typename BasicJsonType::parser_callback_t; 7137 using parse_event_t = typename BasicJsonType::parse_event_t; 7138 7139 json_sax_dom_callback_parser(BasicJsonType& r, 7140 parser_callback_t cb, 7141 const bool allow_exceptions_ = true) 7142 : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_) 7143 { 7144 keep_stack.push_back(true); 7145 } 7146 7147 // make class move-only 7148 json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; 7149 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 7150 json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; 7151 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 7152 ~json_sax_dom_callback_parser() = default; 7153 7154 bool null() 7155 { 7156 handle_value(nullptr); 7157 return true; 7158 } 7159 7160 bool boolean(bool val) 7161 { 7162 handle_value(val); 7163 return true; 7164 } 7165 7166 bool number_integer(number_integer_t val) 7167 { 7168 handle_value(val); 7169 return true; 7170 } 7171 7172 bool number_unsigned(number_unsigned_t val) 7173 { 7174 handle_value(val); 7175 return true; 7176 } 7177 7178 bool number_float(number_float_t val, const string_t& /*unused*/) 7179 { 7180 handle_value(val); 7181 return true; 7182 } 7183 7184 bool string(string_t& val) 7185 { 7186 handle_value(val); 7187 return true; 7188 } 7189 7190 bool binary(binary_t& val) 7191 { 7192 handle_value(std::move(val)); 7193 return true; 7194 } 7195 7196 bool start_object(std::size_t len) 7197 { 7198 // check callback for object start 7199 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded); 7200 keep_stack.push_back(keep); 7201 7202 auto val = handle_value(BasicJsonType::value_t::object, true); 7203 ref_stack.push_back(val.second); 7204 7205 // check object limit 7206 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) 7207 { 7208 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); 7209 } 7210 7211 return true; 7212 } 7213 7214 bool key(string_t& val) 7215 { 7216 BasicJsonType k = BasicJsonType(val); 7217 7218 // check callback for key 7219 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k); 7220 key_keep_stack.push_back(keep); 7221 7222 // add discarded value at given key and store the reference for later 7223 if (keep && ref_stack.back()) 7224 { 7225 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded); 7226 } 7227 7228 return true; 7229 } 7230 7231 bool end_object() 7232 { 7233 if (ref_stack.back()) 7234 { 7235 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) 7236 { 7237 // discard object 7238 *ref_stack.back() = discarded; 7239 } 7240 else 7241 { 7242 ref_stack.back()->set_parents(); 7243 } 7244 } 7245 7246 JSON_ASSERT(!ref_stack.empty()); 7247 JSON_ASSERT(!keep_stack.empty()); 7248 ref_stack.pop_back(); 7249 keep_stack.pop_back(); 7250 7251 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) 7252 { 7253 // remove discarded value 7254 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) 7255 { 7256 if (it->is_discarded()) 7257 { 7258 ref_stack.back()->erase(it); 7259 break; 7260 } 7261 } 7262 } 7263 7264 return true; 7265 } 7266 7267 bool start_array(std::size_t len) 7268 { 7269 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded); 7270 keep_stack.push_back(keep); 7271 7272 auto val = handle_value(BasicJsonType::value_t::array, true); 7273 ref_stack.push_back(val.second); 7274 7275 // check array limit 7276 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) 7277 { 7278 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); 7279 } 7280 7281 return true; 7282 } 7283 7284 bool end_array() 7285 { 7286 bool keep = true; 7287 7288 if (ref_stack.back()) 7289 { 7290 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); 7291 if (keep) 7292 { 7293 ref_stack.back()->set_parents(); 7294 } 7295 else 7296 { 7297 // discard array 7298 *ref_stack.back() = discarded; 7299 } 7300 } 7301 7302 JSON_ASSERT(!ref_stack.empty()); 7303 JSON_ASSERT(!keep_stack.empty()); 7304 ref_stack.pop_back(); 7305 keep_stack.pop_back(); 7306 7307 // remove discarded value 7308 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) 7309 { 7310 ref_stack.back()->m_data.m_value.array->pop_back(); 7311 } 7312 7313 return true; 7314 } 7315 7316 template<class Exception> 7317 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, 7318 const Exception& ex) 7319 { 7320 errored = true; 7321 static_cast<void>(ex); 7322 if (allow_exceptions) 7323 { 7324 JSON_THROW(ex); 7325 } 7326 return false; 7327 } 7328 7329 constexpr bool is_errored() const 7330 { 7331 return errored; 7332 } 7333 7334 private: 7335 /*! 7336 @param[in] v value to add to the JSON value we build during parsing 7337 @param[in] skip_callback whether we should skip calling the callback 7338 function; this is required after start_array() and 7339 start_object() SAX events, because otherwise we would call the 7340 callback function with an empty array or object, respectively. 7341 7342 @invariant If the ref stack is empty, then the passed value will be the new 7343 root. 7344 @invariant If the ref stack contains a value, then it is an array or an 7345 object to which we can add elements 7346 7347 @return pair of boolean (whether value should be kept) and pointer (to the 7348 passed value in the ref_stack hierarchy; nullptr if not kept) 7349 */ 7350 template<typename Value> 7351 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false) 7352 { 7353 JSON_ASSERT(!keep_stack.empty()); 7354 7355 // do not handle this value if we know it would be added to a discarded 7356 // container 7357 if (!keep_stack.back()) 7358 { 7359 return {false, nullptr}; 7360 } 7361 7362 // create value 7363 auto value = BasicJsonType(std::forward<Value>(v)); 7364 7365 // check callback 7366 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value); 7367 7368 // do not handle this value if we just learnt it shall be discarded 7369 if (!keep) 7370 { 7371 return {false, nullptr}; 7372 } 7373 7374 if (ref_stack.empty()) 7375 { 7376 root = std::move(value); 7377 return {true, & root}; 7378 } 7379 7380 // skip this value if we already decided to skip the parent 7381 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) 7382 if (!ref_stack.back()) 7383 { 7384 return {false, nullptr}; 7385 } 7386 7387 // we now only expect arrays and objects 7388 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); 7389 7390 // array 7391 if (ref_stack.back()->is_array()) 7392 { 7393 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value)); 7394 return {true, & (ref_stack.back()->m_data.m_value.array->back())}; 7395 } 7396 7397 // object 7398 JSON_ASSERT(ref_stack.back()->is_object()); 7399 // check if we should store an element for the current key 7400 JSON_ASSERT(!key_keep_stack.empty()); 7401 const bool store_element = key_keep_stack.back(); 7402 key_keep_stack.pop_back(); 7403 7404 if (!store_element) 7405 { 7406 return {false, nullptr}; 7407 } 7408 7409 JSON_ASSERT(object_element); 7410 *object_element = std::move(value); 7411 return {true, object_element}; 7412 } 7413 7414 /// the parsed JSON value 7415 BasicJsonType& root; 7416 /// stack to model hierarchy of values 7417 std::vector<BasicJsonType*> ref_stack {}; 7418 /// stack to manage which values to keep 7419 std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init) 7420 /// stack to manage which object keys to keep 7421 std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init) 7422 /// helper to hold the reference for the next object element 7423 BasicJsonType* object_element = nullptr; 7424 /// whether a syntax error occurred 7425 bool errored = false; 7426 /// callback function 7427 const parser_callback_t callback = nullptr; 7428 /// whether to throw exceptions in case of errors 7429 const bool allow_exceptions = true; 7430 /// a discarded value for the callback 7431 BasicJsonType discarded = BasicJsonType::value_t::discarded; 7432 }; 7433 7434 template<typename BasicJsonType> 7435 class json_sax_acceptor 7436 { 7437 public: 7438 using number_integer_t = typename BasicJsonType::number_integer_t; 7439 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 7440 using number_float_t = typename BasicJsonType::number_float_t; 7441 using string_t = typename BasicJsonType::string_t; 7442 using binary_t = typename BasicJsonType::binary_t; 7443 7444 bool null() 7445 { 7446 return true; 7447 } 7448 7449 bool boolean(bool /*unused*/) 7450 { 7451 return true; 7452 } 7453 7454 bool number_integer(number_integer_t /*unused*/) 7455 { 7456 return true; 7457 } 7458 7459 bool number_unsigned(number_unsigned_t /*unused*/) 7460 { 7461 return true; 7462 } 7463 7464 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) 7465 { 7466 return true; 7467 } 7468 7469 bool string(string_t& /*unused*/) 7470 { 7471 return true; 7472 } 7473 7474 bool binary(binary_t& /*unused*/) 7475 { 7476 return true; 7477 } 7478 7479 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) 7480 { 7481 return true; 7482 } 7483 7484 bool key(string_t& /*unused*/) 7485 { 7486 return true; 7487 } 7488 7489 bool end_object() 7490 { 7491 return true; 7492 } 7493 7494 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) 7495 { 7496 return true; 7497 } 7498 7499 bool end_array() 7500 { 7501 return true; 7502 } 7503 7504 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) 7505 { 7506 return false; 7507 } 7508 }; 7509 7510 } // namespace detail 7511 NLOHMANN_JSON_NAMESPACE_END 7512 7513 // #include <nlohmann/detail/input/lexer.hpp> 7514 // __ _____ _____ _____ 7515 // __| | __| | | | JSON for Modern C++ 7516 // | | |__ | | | | | | version 3.11.3 7517 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 7518 // 7519 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 7520 // SPDX-License-Identifier: MIT 7521 7522 7523 7524 #include <array> // array 7525 #include <clocale> // localeconv 7526 #include <cstddef> // size_t 7527 #include <cstdio> // snprintf 7528 #include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull 7529 #include <initializer_list> // initializer_list 7530 #include <string> // char_traits, string 7531 #include <utility> // move 7532 #include <vector> // vector 7533 7534 // #include <nlohmann/detail/input/input_adapters.hpp> 7535 7536 // #include <nlohmann/detail/input/position_t.hpp> 7537 7538 // #include <nlohmann/detail/macro_scope.hpp> 7539 7540 // #include <nlohmann/detail/meta/type_traits.hpp> 7541 7542 7543 NLOHMANN_JSON_NAMESPACE_BEGIN 7544 namespace detail 7545 { 7546 7547 /////////// 7548 // lexer // 7549 /////////// 7550 7551 template<typename BasicJsonType> 7552 class lexer_base 7553 { 7554 public: 7555 /// token types for the parser 7556 enum class token_type 7557 { 7558 uninitialized, ///< indicating the scanner is uninitialized 7559 literal_true, ///< the `true` literal 7560 literal_false, ///< the `false` literal 7561 literal_null, ///< the `null` literal 7562 value_string, ///< a string -- use get_string() for actual value 7563 value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value 7564 value_integer, ///< a signed integer -- use get_number_integer() for actual value 7565 value_float, ///< an floating point number -- use get_number_float() for actual value 7566 begin_array, ///< the character for array begin `[` 7567 begin_object, ///< the character for object begin `{` 7568 end_array, ///< the character for array end `]` 7569 end_object, ///< the character for object end `}` 7570 name_separator, ///< the name separator `:` 7571 value_separator, ///< the value separator `,` 7572 parse_error, ///< indicating a parse error 7573 end_of_input, ///< indicating the end of the input buffer 7574 literal_or_value ///< a literal or the begin of a value (only for diagnostics) 7575 }; 7576 7577 /// return name of values of type token_type (only used for errors) 7578 JSON_HEDLEY_RETURNS_NON_NULL 7579 JSON_HEDLEY_CONST 7580 static const char* token_type_name(const token_type t) noexcept 7581 { 7582 switch (t) 7583 { 7584 case token_type::uninitialized: 7585 return "<uninitialized>"; 7586 case token_type::literal_true: 7587 return "true literal"; 7588 case token_type::literal_false: 7589 return "false literal"; 7590 case token_type::literal_null: 7591 return "null literal"; 7592 case token_type::value_string: 7593 return "string literal"; 7594 case token_type::value_unsigned: 7595 case token_type::value_integer: 7596 case token_type::value_float: 7597 return "number literal"; 7598 case token_type::begin_array: 7599 return "'['"; 7600 case token_type::begin_object: 7601 return "'{'"; 7602 case token_type::end_array: 7603 return "']'"; 7604 case token_type::end_object: 7605 return "'}'"; 7606 case token_type::name_separator: 7607 return "':'"; 7608 case token_type::value_separator: 7609 return "','"; 7610 case token_type::parse_error: 7611 return "<parse error>"; 7612 case token_type::end_of_input: 7613 return "end of input"; 7614 case token_type::literal_or_value: 7615 return "'[', '{', or a literal"; 7616 // LCOV_EXCL_START 7617 default: // catch non-enum values 7618 return "unknown token"; 7619 // LCOV_EXCL_STOP 7620 } 7621 } 7622 }; 7623 /*! 7624 @brief lexical analysis 7625 7626 This class organizes the lexical analysis during JSON deserialization. 7627 */ 7628 template<typename BasicJsonType, typename InputAdapterType> 7629 class lexer : public lexer_base<BasicJsonType> 7630 { 7631 using number_integer_t = typename BasicJsonType::number_integer_t; 7632 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 7633 using number_float_t = typename BasicJsonType::number_float_t; 7634 using string_t = typename BasicJsonType::string_t; 7635 using char_type = typename InputAdapterType::char_type; 7636 using char_int_type = typename char_traits<char_type>::int_type; 7637 7638 public: 7639 using token_type = typename lexer_base<BasicJsonType>::token_type; 7640 7641 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept 7642 : ia(std::move(adapter)) 7643 , ignore_comments(ignore_comments_) 7644 , decimal_point_char(static_cast<char_int_type>(get_decimal_point())) 7645 {} 7646 7647 // delete because of pointer members 7648 lexer(const lexer&) = delete; 7649 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 7650 lexer& operator=(lexer&) = delete; 7651 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 7652 ~lexer() = default; 7653 7654 private: 7655 ///////////////////// 7656 // locales 7657 ///////////////////// 7658 7659 /// return the locale-dependent decimal point 7660 JSON_HEDLEY_PURE 7661 static char get_decimal_point() noexcept 7662 { 7663 const auto* loc = localeconv(); 7664 JSON_ASSERT(loc != nullptr); 7665 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point); 7666 } 7667 7668 ///////////////////// 7669 // scan functions 7670 ///////////////////// 7671 7672 /*! 7673 @brief get codepoint from 4 hex characters following `\u` 7674 7675 For input "\u c1 c2 c3 c4" the codepoint is: 7676 (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 7677 = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0) 7678 7679 Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' 7680 must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The 7681 conversion is done by subtracting the offset (0x30, 0x37, and 0x57) 7682 between the ASCII value of the character and the desired integer value. 7683 7684 @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or 7685 non-hex character) 7686 */ 7687 int get_codepoint() 7688 { 7689 // this function only makes sense after reading `\u` 7690 JSON_ASSERT(current == 'u'); 7691 int codepoint = 0; 7692 7693 const auto factors = { 12u, 8u, 4u, 0u }; 7694 for (const auto factor : factors) 7695 { 7696 get(); 7697 7698 if (current >= '0' && current <= '9') 7699 { 7700 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor); 7701 } 7702 else if (current >= 'A' && current <= 'F') 7703 { 7704 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor); 7705 } 7706 else if (current >= 'a' && current <= 'f') 7707 { 7708 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor); 7709 } 7710 else 7711 { 7712 return -1; 7713 } 7714 } 7715 7716 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF); 7717 return codepoint; 7718 } 7719 7720 /*! 7721 @brief check if the next byte(s) are inside a given range 7722 7723 Adds the current byte and, for each passed range, reads a new byte and 7724 checks if it is inside the range. If a violation was detected, set up an 7725 error message and return false. Otherwise, return true. 7726 7727 @param[in] ranges list of integers; interpreted as list of pairs of 7728 inclusive lower and upper bound, respectively 7729 7730 @pre The passed list @a ranges must have 2, 4, or 6 elements; that is, 7731 1, 2, or 3 pairs. This precondition is enforced by an assertion. 7732 7733 @return true if and only if no range violation was detected 7734 */ 7735 bool next_byte_in_range(std::initializer_list<char_int_type> ranges) 7736 { 7737 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6); 7738 add(current); 7739 7740 for (auto range = ranges.begin(); range != ranges.end(); ++range) 7741 { 7742 get(); 7743 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions) 7744 { 7745 add(current); 7746 } 7747 else 7748 { 7749 error_message = "invalid string: ill-formed UTF-8 byte"; 7750 return false; 7751 } 7752 } 7753 7754 return true; 7755 } 7756 7757 /*! 7758 @brief scan a string literal 7759 7760 This function scans a string according to Sect. 7 of RFC 8259. While 7761 scanning, bytes are escaped and copied into buffer token_buffer. Then the 7762 function returns successfully, token_buffer is *not* null-terminated (as it 7763 may contain \0 bytes), and token_buffer.size() is the number of bytes in the 7764 string. 7765 7766 @return token_type::value_string if string could be successfully scanned, 7767 token_type::parse_error otherwise 7768 7769 @note In case of errors, variable error_message contains a textual 7770 description. 7771 */ 7772 token_type scan_string() 7773 { 7774 // reset token_buffer (ignore opening quote) 7775 reset(); 7776 7777 // we entered the function by reading an open quote 7778 JSON_ASSERT(current == '\"'); 7779 7780 while (true) 7781 { 7782 // get next character 7783 switch (get()) 7784 { 7785 // end of file while parsing string 7786 case char_traits<char_type>::eof(): 7787 { 7788 error_message = "invalid string: missing closing quote"; 7789 return token_type::parse_error; 7790 } 7791 7792 // closing quote 7793 case '\"': 7794 { 7795 return token_type::value_string; 7796 } 7797 7798 // escapes 7799 case '\\': 7800 { 7801 switch (get()) 7802 { 7803 // quotation mark 7804 case '\"': 7805 add('\"'); 7806 break; 7807 // reverse solidus 7808 case '\\': 7809 add('\\'); 7810 break; 7811 // solidus 7812 case '/': 7813 add('/'); 7814 break; 7815 // backspace 7816 case 'b': 7817 add('\b'); 7818 break; 7819 // form feed 7820 case 'f': 7821 add('\f'); 7822 break; 7823 // line feed 7824 case 'n': 7825 add('\n'); 7826 break; 7827 // carriage return 7828 case 'r': 7829 add('\r'); 7830 break; 7831 // tab 7832 case 't': 7833 add('\t'); 7834 break; 7835 7836 // unicode escapes 7837 case 'u': 7838 { 7839 const int codepoint1 = get_codepoint(); 7840 int codepoint = codepoint1; // start with codepoint1 7841 7842 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) 7843 { 7844 error_message = "invalid string: '\\u' must be followed by 4 hex digits"; 7845 return token_type::parse_error; 7846 } 7847 7848 // check if code point is a high surrogate 7849 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) 7850 { 7851 // expect next \uxxxx entry 7852 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) 7853 { 7854 const int codepoint2 = get_codepoint(); 7855 7856 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) 7857 { 7858 error_message = "invalid string: '\\u' must be followed by 4 hex digits"; 7859 return token_type::parse_error; 7860 } 7861 7862 // check if codepoint2 is a low surrogate 7863 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF)) 7864 { 7865 // overwrite codepoint 7866 codepoint = static_cast<int>( 7867 // high surrogate occupies the most significant 22 bits 7868 (static_cast<unsigned int>(codepoint1) << 10u) 7869 // low surrogate occupies the least significant 15 bits 7870 + static_cast<unsigned int>(codepoint2) 7871 // there is still the 0xD800, 0xDC00 and 0x10000 noise 7872 // in the result, so we have to subtract with: 7873 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 7874 - 0x35FDC00u); 7875 } 7876 else 7877 { 7878 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; 7879 return token_type::parse_error; 7880 } 7881 } 7882 else 7883 { 7884 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; 7885 return token_type::parse_error; 7886 } 7887 } 7888 else 7889 { 7890 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF)) 7891 { 7892 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF"; 7893 return token_type::parse_error; 7894 } 7895 } 7896 7897 // result of the above calculation yields a proper codepoint 7898 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF); 7899 7900 // translate codepoint into bytes 7901 if (codepoint < 0x80) 7902 { 7903 // 1-byte characters: 0xxxxxxx (ASCII) 7904 add(static_cast<char_int_type>(codepoint)); 7905 } 7906 else if (codepoint <= 0x7FF) 7907 { 7908 // 2-byte characters: 110xxxxx 10xxxxxx 7909 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u))); 7910 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu))); 7911 } 7912 else if (codepoint <= 0xFFFF) 7913 { 7914 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx 7915 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u))); 7916 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu))); 7917 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu))); 7918 } 7919 else 7920 { 7921 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 7922 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u))); 7923 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu))); 7924 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu))); 7925 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu))); 7926 } 7927 7928 break; 7929 } 7930 7931 // other characters after escape 7932 default: 7933 error_message = "invalid string: forbidden character after backslash"; 7934 return token_type::parse_error; 7935 } 7936 7937 break; 7938 } 7939 7940 // invalid control characters 7941 case 0x00: 7942 { 7943 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; 7944 return token_type::parse_error; 7945 } 7946 7947 case 0x01: 7948 { 7949 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; 7950 return token_type::parse_error; 7951 } 7952 7953 case 0x02: 7954 { 7955 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; 7956 return token_type::parse_error; 7957 } 7958 7959 case 0x03: 7960 { 7961 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; 7962 return token_type::parse_error; 7963 } 7964 7965 case 0x04: 7966 { 7967 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; 7968 return token_type::parse_error; 7969 } 7970 7971 case 0x05: 7972 { 7973 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; 7974 return token_type::parse_error; 7975 } 7976 7977 case 0x06: 7978 { 7979 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; 7980 return token_type::parse_error; 7981 } 7982 7983 case 0x07: 7984 { 7985 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; 7986 return token_type::parse_error; 7987 } 7988 7989 case 0x08: 7990 { 7991 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; 7992 return token_type::parse_error; 7993 } 7994 7995 case 0x09: 7996 { 7997 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; 7998 return token_type::parse_error; 7999 } 8000 8001 case 0x0A: 8002 { 8003 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; 8004 return token_type::parse_error; 8005 } 8006 8007 case 0x0B: 8008 { 8009 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; 8010 return token_type::parse_error; 8011 } 8012 8013 case 0x0C: 8014 { 8015 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; 8016 return token_type::parse_error; 8017 } 8018 8019 case 0x0D: 8020 { 8021 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; 8022 return token_type::parse_error; 8023 } 8024 8025 case 0x0E: 8026 { 8027 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; 8028 return token_type::parse_error; 8029 } 8030 8031 case 0x0F: 8032 { 8033 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; 8034 return token_type::parse_error; 8035 } 8036 8037 case 0x10: 8038 { 8039 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; 8040 return token_type::parse_error; 8041 } 8042 8043 case 0x11: 8044 { 8045 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; 8046 return token_type::parse_error; 8047 } 8048 8049 case 0x12: 8050 { 8051 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; 8052 return token_type::parse_error; 8053 } 8054 8055 case 0x13: 8056 { 8057 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; 8058 return token_type::parse_error; 8059 } 8060 8061 case 0x14: 8062 { 8063 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; 8064 return token_type::parse_error; 8065 } 8066 8067 case 0x15: 8068 { 8069 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; 8070 return token_type::parse_error; 8071 } 8072 8073 case 0x16: 8074 { 8075 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; 8076 return token_type::parse_error; 8077 } 8078 8079 case 0x17: 8080 { 8081 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; 8082 return token_type::parse_error; 8083 } 8084 8085 case 0x18: 8086 { 8087 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; 8088 return token_type::parse_error; 8089 } 8090 8091 case 0x19: 8092 { 8093 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; 8094 return token_type::parse_error; 8095 } 8096 8097 case 0x1A: 8098 { 8099 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; 8100 return token_type::parse_error; 8101 } 8102 8103 case 0x1B: 8104 { 8105 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; 8106 return token_type::parse_error; 8107 } 8108 8109 case 0x1C: 8110 { 8111 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; 8112 return token_type::parse_error; 8113 } 8114 8115 case 0x1D: 8116 { 8117 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; 8118 return token_type::parse_error; 8119 } 8120 8121 case 0x1E: 8122 { 8123 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; 8124 return token_type::parse_error; 8125 } 8126 8127 case 0x1F: 8128 { 8129 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; 8130 return token_type::parse_error; 8131 } 8132 8133 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) 8134 case 0x20: 8135 case 0x21: 8136 case 0x23: 8137 case 0x24: 8138 case 0x25: 8139 case 0x26: 8140 case 0x27: 8141 case 0x28: 8142 case 0x29: 8143 case 0x2A: 8144 case 0x2B: 8145 case 0x2C: 8146 case 0x2D: 8147 case 0x2E: 8148 case 0x2F: 8149 case 0x30: 8150 case 0x31: 8151 case 0x32: 8152 case 0x33: 8153 case 0x34: 8154 case 0x35: 8155 case 0x36: 8156 case 0x37: 8157 case 0x38: 8158 case 0x39: 8159 case 0x3A: 8160 case 0x3B: 8161 case 0x3C: 8162 case 0x3D: 8163 case 0x3E: 8164 case 0x3F: 8165 case 0x40: 8166 case 0x41: 8167 case 0x42: 8168 case 0x43: 8169 case 0x44: 8170 case 0x45: 8171 case 0x46: 8172 case 0x47: 8173 case 0x48: 8174 case 0x49: 8175 case 0x4A: 8176 case 0x4B: 8177 case 0x4C: 8178 case 0x4D: 8179 case 0x4E: 8180 case 0x4F: 8181 case 0x50: 8182 case 0x51: 8183 case 0x52: 8184 case 0x53: 8185 case 0x54: 8186 case 0x55: 8187 case 0x56: 8188 case 0x57: 8189 case 0x58: 8190 case 0x59: 8191 case 0x5A: 8192 case 0x5B: 8193 case 0x5D: 8194 case 0x5E: 8195 case 0x5F: 8196 case 0x60: 8197 case 0x61: 8198 case 0x62: 8199 case 0x63: 8200 case 0x64: 8201 case 0x65: 8202 case 0x66: 8203 case 0x67: 8204 case 0x68: 8205 case 0x69: 8206 case 0x6A: 8207 case 0x6B: 8208 case 0x6C: 8209 case 0x6D: 8210 case 0x6E: 8211 case 0x6F: 8212 case 0x70: 8213 case 0x71: 8214 case 0x72: 8215 case 0x73: 8216 case 0x74: 8217 case 0x75: 8218 case 0x76: 8219 case 0x77: 8220 case 0x78: 8221 case 0x79: 8222 case 0x7A: 8223 case 0x7B: 8224 case 0x7C: 8225 case 0x7D: 8226 case 0x7E: 8227 case 0x7F: 8228 { 8229 add(current); 8230 break; 8231 } 8232 8233 // U+0080..U+07FF: bytes C2..DF 80..BF 8234 case 0xC2: 8235 case 0xC3: 8236 case 0xC4: 8237 case 0xC5: 8238 case 0xC6: 8239 case 0xC7: 8240 case 0xC8: 8241 case 0xC9: 8242 case 0xCA: 8243 case 0xCB: 8244 case 0xCC: 8245 case 0xCD: 8246 case 0xCE: 8247 case 0xCF: 8248 case 0xD0: 8249 case 0xD1: 8250 case 0xD2: 8251 case 0xD3: 8252 case 0xD4: 8253 case 0xD5: 8254 case 0xD6: 8255 case 0xD7: 8256 case 0xD8: 8257 case 0xD9: 8258 case 0xDA: 8259 case 0xDB: 8260 case 0xDC: 8261 case 0xDD: 8262 case 0xDE: 8263 case 0xDF: 8264 { 8265 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF}))) 8266 { 8267 return token_type::parse_error; 8268 } 8269 break; 8270 } 8271 8272 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF 8273 case 0xE0: 8274 { 8275 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) 8276 { 8277 return token_type::parse_error; 8278 } 8279 break; 8280 } 8281 8282 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF 8283 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF 8284 case 0xE1: 8285 case 0xE2: 8286 case 0xE3: 8287 case 0xE4: 8288 case 0xE5: 8289 case 0xE6: 8290 case 0xE7: 8291 case 0xE8: 8292 case 0xE9: 8293 case 0xEA: 8294 case 0xEB: 8295 case 0xEC: 8296 case 0xEE: 8297 case 0xEF: 8298 { 8299 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) 8300 { 8301 return token_type::parse_error; 8302 } 8303 break; 8304 } 8305 8306 // U+D000..U+D7FF: bytes ED 80..9F 80..BF 8307 case 0xED: 8308 { 8309 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) 8310 { 8311 return token_type::parse_error; 8312 } 8313 break; 8314 } 8315 8316 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF 8317 case 0xF0: 8318 { 8319 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) 8320 { 8321 return token_type::parse_error; 8322 } 8323 break; 8324 } 8325 8326 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF 8327 case 0xF1: 8328 case 0xF2: 8329 case 0xF3: 8330 { 8331 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) 8332 { 8333 return token_type::parse_error; 8334 } 8335 break; 8336 } 8337 8338 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF 8339 case 0xF4: 8340 { 8341 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) 8342 { 8343 return token_type::parse_error; 8344 } 8345 break; 8346 } 8347 8348 // remaining bytes (80..C1 and F5..FF) are ill-formed 8349 default: 8350 { 8351 error_message = "invalid string: ill-formed UTF-8 byte"; 8352 return token_type::parse_error; 8353 } 8354 } 8355 } 8356 } 8357 8358 /*! 8359 * @brief scan a comment 8360 * @return whether comment could be scanned successfully 8361 */ 8362 bool scan_comment() 8363 { 8364 switch (get()) 8365 { 8366 // single-line comments skip input until a newline or EOF is read 8367 case '/': 8368 { 8369 while (true) 8370 { 8371 switch (get()) 8372 { 8373 case '\n': 8374 case '\r': 8375 case char_traits<char_type>::eof(): 8376 case '\0': 8377 return true; 8378 8379 default: 8380 break; 8381 } 8382 } 8383 } 8384 8385 // multi-line comments skip input until */ is read 8386 case '*': 8387 { 8388 while (true) 8389 { 8390 switch (get()) 8391 { 8392 case char_traits<char_type>::eof(): 8393 case '\0': 8394 { 8395 error_message = "invalid comment; missing closing '*/'"; 8396 return false; 8397 } 8398 8399 case '*': 8400 { 8401 switch (get()) 8402 { 8403 case '/': 8404 return true; 8405 8406 default: 8407 { 8408 unget(); 8409 continue; 8410 } 8411 } 8412 } 8413 8414 default: 8415 continue; 8416 } 8417 } 8418 } 8419 8420 // unexpected character after reading '/' 8421 default: 8422 { 8423 error_message = "invalid comment; expecting '/' or '*' after '/'"; 8424 return false; 8425 } 8426 } 8427 } 8428 8429 JSON_HEDLEY_NON_NULL(2) 8430 static void strtof(float& f, const char* str, char** endptr) noexcept 8431 { 8432 f = std::strtof(str, endptr); 8433 } 8434 8435 JSON_HEDLEY_NON_NULL(2) 8436 static void strtof(double& f, const char* str, char** endptr) noexcept 8437 { 8438 f = std::strtod(str, endptr); 8439 } 8440 8441 JSON_HEDLEY_NON_NULL(2) 8442 static void strtof(long double& f, const char* str, char** endptr) noexcept 8443 { 8444 f = std::strtold(str, endptr); 8445 } 8446 8447 /*! 8448 @brief scan a number literal 8449 8450 This function scans a string according to Sect. 6 of RFC 8259. 8451 8452 The function is realized with a deterministic finite state machine derived 8453 from the grammar described in RFC 8259. Starting in state "init", the 8454 input is read and used to determined the next state. Only state "done" 8455 accepts the number. State "error" is a trap state to model errors. In the 8456 table below, "anything" means any character but the ones listed before. 8457 8458 state | 0 | 1-9 | e E | + | - | . | anything 8459 ---------|----------|----------|----------|---------|---------|----------|----------- 8460 init | zero | any1 | [error] | [error] | minus | [error] | [error] 8461 minus | zero | any1 | [error] | [error] | [error] | [error] | [error] 8462 zero | done | done | exponent | done | done | decimal1 | done 8463 any1 | any1 | any1 | exponent | done | done | decimal1 | done 8464 decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error] 8465 decimal2 | decimal2 | decimal2 | exponent | done | done | done | done 8466 exponent | any2 | any2 | [error] | sign | sign | [error] | [error] 8467 sign | any2 | any2 | [error] | [error] | [error] | [error] | [error] 8468 any2 | any2 | any2 | done | done | done | done | done 8469 8470 The state machine is realized with one label per state (prefixed with 8471 "scan_number_") and `goto` statements between them. The state machine 8472 contains cycles, but any cycle can be left when EOF is read. Therefore, 8473 the function is guaranteed to terminate. 8474 8475 During scanning, the read bytes are stored in token_buffer. This string is 8476 then converted to a signed integer, an unsigned integer, or a 8477 floating-point number. 8478 8479 @return token_type::value_unsigned, token_type::value_integer, or 8480 token_type::value_float if number could be successfully scanned, 8481 token_type::parse_error otherwise 8482 8483 @note The scanner is independent of the current locale. Internally, the 8484 locale's decimal point is used instead of `.` to work with the 8485 locale-dependent converters. 8486 */ 8487 token_type scan_number() // lgtm [cpp/use-of-goto] `goto` is used in this function to implement the number-parsing state machine described above. By design, any finite input will eventually reach the "done" state or return token_type::parse_error. In each intermediate state, 1 byte of the input is appended to the token_buffer vector, and only the already initialized variables token_buffer, number_type, and error_message are manipulated. 8488 { 8489 // reset token_buffer to store the number's bytes 8490 reset(); 8491 8492 // the type of the parsed number; initially set to unsigned; will be 8493 // changed if minus sign, decimal point or exponent is read 8494 token_type number_type = token_type::value_unsigned; 8495 8496 // state (init): we just found out we need to scan a number 8497 switch (current) 8498 { 8499 case '-': 8500 { 8501 add(current); 8502 goto scan_number_minus; 8503 } 8504 8505 case '0': 8506 { 8507 add(current); 8508 goto scan_number_zero; 8509 } 8510 8511 case '1': 8512 case '2': 8513 case '3': 8514 case '4': 8515 case '5': 8516 case '6': 8517 case '7': 8518 case '8': 8519 case '9': 8520 { 8521 add(current); 8522 goto scan_number_any1; 8523 } 8524 8525 // all other characters are rejected outside scan_number() 8526 default: // LCOV_EXCL_LINE 8527 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 8528 } 8529 8530 scan_number_minus: 8531 // state: we just parsed a leading minus sign 8532 number_type = token_type::value_integer; 8533 switch (get()) 8534 { 8535 case '0': 8536 { 8537 add(current); 8538 goto scan_number_zero; 8539 } 8540 8541 case '1': 8542 case '2': 8543 case '3': 8544 case '4': 8545 case '5': 8546 case '6': 8547 case '7': 8548 case '8': 8549 case '9': 8550 { 8551 add(current); 8552 goto scan_number_any1; 8553 } 8554 8555 default: 8556 { 8557 error_message = "invalid number; expected digit after '-'"; 8558 return token_type::parse_error; 8559 } 8560 } 8561 8562 scan_number_zero: 8563 // state: we just parse a zero (maybe with a leading minus sign) 8564 switch (get()) 8565 { 8566 case '.': 8567 { 8568 add(decimal_point_char); 8569 decimal_point_position = token_buffer.size() - 1; 8570 goto scan_number_decimal1; 8571 } 8572 8573 case 'e': 8574 case 'E': 8575 { 8576 add(current); 8577 goto scan_number_exponent; 8578 } 8579 8580 default: 8581 goto scan_number_done; 8582 } 8583 8584 scan_number_any1: 8585 // state: we just parsed a number 0-9 (maybe with a leading minus sign) 8586 switch (get()) 8587 { 8588 case '0': 8589 case '1': 8590 case '2': 8591 case '3': 8592 case '4': 8593 case '5': 8594 case '6': 8595 case '7': 8596 case '8': 8597 case '9': 8598 { 8599 add(current); 8600 goto scan_number_any1; 8601 } 8602 8603 case '.': 8604 { 8605 add(decimal_point_char); 8606 decimal_point_position = token_buffer.size() - 1; 8607 goto scan_number_decimal1; 8608 } 8609 8610 case 'e': 8611 case 'E': 8612 { 8613 add(current); 8614 goto scan_number_exponent; 8615 } 8616 8617 default: 8618 goto scan_number_done; 8619 } 8620 8621 scan_number_decimal1: 8622 // state: we just parsed a decimal point 8623 number_type = token_type::value_float; 8624 switch (get()) 8625 { 8626 case '0': 8627 case '1': 8628 case '2': 8629 case '3': 8630 case '4': 8631 case '5': 8632 case '6': 8633 case '7': 8634 case '8': 8635 case '9': 8636 { 8637 add(current); 8638 goto scan_number_decimal2; 8639 } 8640 8641 default: 8642 { 8643 error_message = "invalid number; expected digit after '.'"; 8644 return token_type::parse_error; 8645 } 8646 } 8647 8648 scan_number_decimal2: 8649 // we just parsed at least one number after a decimal point 8650 switch (get()) 8651 { 8652 case '0': 8653 case '1': 8654 case '2': 8655 case '3': 8656 case '4': 8657 case '5': 8658 case '6': 8659 case '7': 8660 case '8': 8661 case '9': 8662 { 8663 add(current); 8664 goto scan_number_decimal2; 8665 } 8666 8667 case 'e': 8668 case 'E': 8669 { 8670 add(current); 8671 goto scan_number_exponent; 8672 } 8673 8674 default: 8675 goto scan_number_done; 8676 } 8677 8678 scan_number_exponent: 8679 // we just parsed an exponent 8680 number_type = token_type::value_float; 8681 switch (get()) 8682 { 8683 case '+': 8684 case '-': 8685 { 8686 add(current); 8687 goto scan_number_sign; 8688 } 8689 8690 case '0': 8691 case '1': 8692 case '2': 8693 case '3': 8694 case '4': 8695 case '5': 8696 case '6': 8697 case '7': 8698 case '8': 8699 case '9': 8700 { 8701 add(current); 8702 goto scan_number_any2; 8703 } 8704 8705 default: 8706 { 8707 error_message = 8708 "invalid number; expected '+', '-', or digit after exponent"; 8709 return token_type::parse_error; 8710 } 8711 } 8712 8713 scan_number_sign: 8714 // we just parsed an exponent sign 8715 switch (get()) 8716 { 8717 case '0': 8718 case '1': 8719 case '2': 8720 case '3': 8721 case '4': 8722 case '5': 8723 case '6': 8724 case '7': 8725 case '8': 8726 case '9': 8727 { 8728 add(current); 8729 goto scan_number_any2; 8730 } 8731 8732 default: 8733 { 8734 error_message = "invalid number; expected digit after exponent sign"; 8735 return token_type::parse_error; 8736 } 8737 } 8738 8739 scan_number_any2: 8740 // we just parsed a number after the exponent or exponent sign 8741 switch (get()) 8742 { 8743 case '0': 8744 case '1': 8745 case '2': 8746 case '3': 8747 case '4': 8748 case '5': 8749 case '6': 8750 case '7': 8751 case '8': 8752 case '9': 8753 { 8754 add(current); 8755 goto scan_number_any2; 8756 } 8757 8758 default: 8759 goto scan_number_done; 8760 } 8761 8762 scan_number_done: 8763 // unget the character after the number (we only read it to know that 8764 // we are done scanning a number) 8765 unget(); 8766 8767 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 8768 errno = 0; 8769 8770 // try to parse integers first and fall back to floats 8771 if (number_type == token_type::value_unsigned) 8772 { 8773 const auto x = std::strtoull(token_buffer.data(), &endptr, 10); 8774 8775 // we checked the number format before 8776 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); 8777 8778 if (errno != ERANGE) 8779 { 8780 value_unsigned = static_cast<number_unsigned_t>(x); 8781 if (value_unsigned == x) 8782 { 8783 return token_type::value_unsigned; 8784 } 8785 } 8786 } 8787 else if (number_type == token_type::value_integer) 8788 { 8789 const auto x = std::strtoll(token_buffer.data(), &endptr, 10); 8790 8791 // we checked the number format before 8792 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); 8793 8794 if (errno != ERANGE) 8795 { 8796 value_integer = static_cast<number_integer_t>(x); 8797 if (value_integer == x) 8798 { 8799 return token_type::value_integer; 8800 } 8801 } 8802 } 8803 8804 // this code is reached if we parse a floating-point number or if an 8805 // integer conversion above failed 8806 strtof(value_float, token_buffer.data(), &endptr); 8807 8808 // we checked the number format before 8809 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); 8810 8811 return token_type::value_float; 8812 } 8813 8814 /*! 8815 @param[in] literal_text the literal text to expect 8816 @param[in] length the length of the passed literal text 8817 @param[in] return_type the token type to return on success 8818 */ 8819 JSON_HEDLEY_NON_NULL(2) 8820 token_type scan_literal(const char_type* literal_text, const std::size_t length, 8821 token_type return_type) 8822 { 8823 JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]); 8824 for (std::size_t i = 1; i < length; ++i) 8825 { 8826 if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i])) 8827 { 8828 error_message = "invalid literal"; 8829 return token_type::parse_error; 8830 } 8831 } 8832 return return_type; 8833 } 8834 8835 ///////////////////// 8836 // input management 8837 ///////////////////// 8838 8839 /// reset token_buffer; current character is beginning of token 8840 void reset() noexcept 8841 { 8842 token_buffer.clear(); 8843 token_string.clear(); 8844 decimal_point_position = std::string::npos; 8845 token_string.push_back(char_traits<char_type>::to_char_type(current)); 8846 } 8847 8848 /* 8849 @brief get next character from the input 8850 8851 This function provides the interface to the used input adapter. It does 8852 not throw in case the input reached EOF, but returns a 8853 `char_traits<char>::eof()` in that case. Stores the scanned characters 8854 for use in error messages. 8855 8856 @return character read from the input 8857 */ 8858 char_int_type get() 8859 { 8860 ++position.chars_read_total; 8861 ++position.chars_read_current_line; 8862 8863 if (next_unget) 8864 { 8865 // just reset the next_unget variable and work with current 8866 next_unget = false; 8867 } 8868 else 8869 { 8870 current = ia.get_character(); 8871 } 8872 8873 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof())) 8874 { 8875 token_string.push_back(char_traits<char_type>::to_char_type(current)); 8876 } 8877 8878 if (current == '\n') 8879 { 8880 ++position.lines_read; 8881 position.chars_read_current_line = 0; 8882 } 8883 8884 return current; 8885 } 8886 8887 /*! 8888 @brief unget current character (read it again on next get) 8889 8890 We implement unget by setting variable next_unget to true. The input is not 8891 changed - we just simulate ungetting by modifying chars_read_total, 8892 chars_read_current_line, and token_string. The next call to get() will 8893 behave as if the unget character is read again. 8894 */ 8895 void unget() 8896 { 8897 next_unget = true; 8898 8899 --position.chars_read_total; 8900 8901 // in case we "unget" a newline, we have to also decrement the lines_read 8902 if (position.chars_read_current_line == 0) 8903 { 8904 if (position.lines_read > 0) 8905 { 8906 --position.lines_read; 8907 } 8908 } 8909 else 8910 { 8911 --position.chars_read_current_line; 8912 } 8913 8914 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof())) 8915 { 8916 JSON_ASSERT(!token_string.empty()); 8917 token_string.pop_back(); 8918 } 8919 } 8920 8921 /// add a character to token_buffer 8922 void add(char_int_type c) 8923 { 8924 token_buffer.push_back(static_cast<typename string_t::value_type>(c)); 8925 } 8926 8927 public: 8928 ///////////////////// 8929 // value getters 8930 ///////////////////// 8931 8932 /// return integer value 8933 constexpr number_integer_t get_number_integer() const noexcept 8934 { 8935 return value_integer; 8936 } 8937 8938 /// return unsigned integer value 8939 constexpr number_unsigned_t get_number_unsigned() const noexcept 8940 { 8941 return value_unsigned; 8942 } 8943 8944 /// return floating-point value 8945 constexpr number_float_t get_number_float() const noexcept 8946 { 8947 return value_float; 8948 } 8949 8950 /// return current string value (implicitly resets the token; useful only once) 8951 string_t& get_string() 8952 { 8953 // translate decimal points from locale back to '.' (#4084) 8954 if (decimal_point_char != '.' && decimal_point_position != std::string::npos) 8955 { 8956 token_buffer[decimal_point_position] = '.'; 8957 } 8958 return token_buffer; 8959 } 8960 8961 ///////////////////// 8962 // diagnostics 8963 ///////////////////// 8964 8965 /// return position of last read token 8966 constexpr position_t get_position() const noexcept 8967 { 8968 return position; 8969 } 8970 8971 /// return the last read token (for errors only). Will never contain EOF 8972 /// (an arbitrary value that is not a valid char value, often -1), because 8973 /// 255 may legitimately occur. May contain NUL, which should be escaped. 8974 std::string get_token_string() const 8975 { 8976 // escape control characters 8977 std::string result; 8978 for (const auto c : token_string) 8979 { 8980 if (static_cast<unsigned char>(c) <= '\x1F') 8981 { 8982 // escape control characters 8983 std::array<char, 9> cs{{}}; 8984 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 8985 result += cs.data(); 8986 } 8987 else 8988 { 8989 // add character as is 8990 result.push_back(static_cast<std::string::value_type>(c)); 8991 } 8992 } 8993 8994 return result; 8995 } 8996 8997 /// return syntax error message 8998 JSON_HEDLEY_RETURNS_NON_NULL 8999 constexpr const char* get_error_message() const noexcept 9000 { 9001 return error_message; 9002 } 9003 9004 ///////////////////// 9005 // actual scanner 9006 ///////////////////// 9007 9008 /*! 9009 @brief skip the UTF-8 byte order mark 9010 @return true iff there is no BOM or the correct BOM has been skipped 9011 */ 9012 bool skip_bom() 9013 { 9014 if (get() == 0xEF) 9015 { 9016 // check if we completely parse the BOM 9017 return get() == 0xBB && get() == 0xBF; 9018 } 9019 9020 // the first character is not the beginning of the BOM; unget it to 9021 // process is later 9022 unget(); 9023 return true; 9024 } 9025 9026 void skip_whitespace() 9027 { 9028 do 9029 { 9030 get(); 9031 } 9032 while (current == ' ' || current == '\t' || current == '\n' || current == '\r'); 9033 } 9034 9035 token_type scan() 9036 { 9037 // initially, skip the BOM 9038 if (position.chars_read_total == 0 && !skip_bom()) 9039 { 9040 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; 9041 return token_type::parse_error; 9042 } 9043 9044 // read next character and ignore whitespace 9045 skip_whitespace(); 9046 9047 // ignore comments 9048 while (ignore_comments && current == '/') 9049 { 9050 if (!scan_comment()) 9051 { 9052 return token_type::parse_error; 9053 } 9054 9055 // skip following whitespace 9056 skip_whitespace(); 9057 } 9058 9059 switch (current) 9060 { 9061 // structural characters 9062 case '[': 9063 return token_type::begin_array; 9064 case ']': 9065 return token_type::end_array; 9066 case '{': 9067 return token_type::begin_object; 9068 case '}': 9069 return token_type::end_object; 9070 case ':': 9071 return token_type::name_separator; 9072 case ',': 9073 return token_type::value_separator; 9074 9075 // literals 9076 case 't': 9077 { 9078 std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')}}; 9079 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); 9080 } 9081 case 'f': 9082 { 9083 std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')}}; 9084 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); 9085 } 9086 case 'n': 9087 { 9088 std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')}}; 9089 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); 9090 } 9091 9092 // string 9093 case '\"': 9094 return scan_string(); 9095 9096 // number 9097 case '-': 9098 case '0': 9099 case '1': 9100 case '2': 9101 case '3': 9102 case '4': 9103 case '5': 9104 case '6': 9105 case '7': 9106 case '8': 9107 case '9': 9108 return scan_number(); 9109 9110 // end of input (the null byte is needed when parsing from 9111 // string literals) 9112 case '\0': 9113 case char_traits<char_type>::eof(): 9114 return token_type::end_of_input; 9115 9116 // error 9117 default: 9118 error_message = "invalid literal"; 9119 return token_type::parse_error; 9120 } 9121 } 9122 9123 private: 9124 /// input adapter 9125 InputAdapterType ia; 9126 9127 /// whether comments should be ignored (true) or signaled as errors (false) 9128 const bool ignore_comments = false; 9129 9130 /// the current character 9131 char_int_type current = char_traits<char_type>::eof(); 9132 9133 /// whether the next get() call should just return current 9134 bool next_unget = false; 9135 9136 /// the start position of the current token 9137 position_t position {}; 9138 9139 /// raw input token string (for error messages) 9140 std::vector<char_type> token_string {}; 9141 9142 /// buffer for variable-length tokens (numbers, strings) 9143 string_t token_buffer {}; 9144 9145 /// a description of occurred lexer errors 9146 const char* error_message = ""; 9147 9148 // number values 9149 number_integer_t value_integer = 0; 9150 number_unsigned_t value_unsigned = 0; 9151 number_float_t value_float = 0; 9152 9153 /// the decimal point 9154 const char_int_type decimal_point_char = '.'; 9155 /// the position of the decimal point in the input 9156 std::size_t decimal_point_position = std::string::npos; 9157 }; 9158 9159 } // namespace detail 9160 NLOHMANN_JSON_NAMESPACE_END 9161 9162 // #include <nlohmann/detail/macro_scope.hpp> 9163 9164 // #include <nlohmann/detail/meta/is_sax.hpp> 9165 // __ _____ _____ _____ 9166 // __| | __| | | | JSON for Modern C++ 9167 // | | |__ | | | | | | version 3.11.3 9168 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 9169 // 9170 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 9171 // SPDX-License-Identifier: MIT 9172 9173 9174 9175 #include <cstdint> // size_t 9176 #include <utility> // declval 9177 #include <string> // string 9178 9179 // #include <nlohmann/detail/abi_macros.hpp> 9180 9181 // #include <nlohmann/detail/meta/detected.hpp> 9182 9183 // #include <nlohmann/detail/meta/type_traits.hpp> 9184 9185 9186 NLOHMANN_JSON_NAMESPACE_BEGIN 9187 namespace detail 9188 { 9189 9190 template<typename T> 9191 using null_function_t = decltype(std::declval<T&>().null()); 9192 9193 template<typename T> 9194 using boolean_function_t = 9195 decltype(std::declval<T&>().boolean(std::declval<bool>())); 9196 9197 template<typename T, typename Integer> 9198 using number_integer_function_t = 9199 decltype(std::declval<T&>().number_integer(std::declval<Integer>())); 9200 9201 template<typename T, typename Unsigned> 9202 using number_unsigned_function_t = 9203 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>())); 9204 9205 template<typename T, typename Float, typename String> 9206 using number_float_function_t = decltype(std::declval<T&>().number_float( 9207 std::declval<Float>(), std::declval<const String&>())); 9208 9209 template<typename T, typename String> 9210 using string_function_t = 9211 decltype(std::declval<T&>().string(std::declval<String&>())); 9212 9213 template<typename T, typename Binary> 9214 using binary_function_t = 9215 decltype(std::declval<T&>().binary(std::declval<Binary&>())); 9216 9217 template<typename T> 9218 using start_object_function_t = 9219 decltype(std::declval<T&>().start_object(std::declval<std::size_t>())); 9220 9221 template<typename T, typename String> 9222 using key_function_t = 9223 decltype(std::declval<T&>().key(std::declval<String&>())); 9224 9225 template<typename T> 9226 using end_object_function_t = decltype(std::declval<T&>().end_object()); 9227 9228 template<typename T> 9229 using start_array_function_t = 9230 decltype(std::declval<T&>().start_array(std::declval<std::size_t>())); 9231 9232 template<typename T> 9233 using end_array_function_t = decltype(std::declval<T&>().end_array()); 9234 9235 template<typename T, typename Exception> 9236 using parse_error_function_t = decltype(std::declval<T&>().parse_error( 9237 std::declval<std::size_t>(), std::declval<const std::string&>(), 9238 std::declval<const Exception&>())); 9239 9240 template<typename SAX, typename BasicJsonType> 9241 struct is_sax 9242 { 9243 private: 9244 static_assert(is_basic_json<BasicJsonType>::value, 9245 "BasicJsonType must be of type basic_json<...>"); 9246 9247 using number_integer_t = typename BasicJsonType::number_integer_t; 9248 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 9249 using number_float_t = typename BasicJsonType::number_float_t; 9250 using string_t = typename BasicJsonType::string_t; 9251 using binary_t = typename BasicJsonType::binary_t; 9252 using exception_t = typename BasicJsonType::exception; 9253 9254 public: 9255 static constexpr bool value = 9256 is_detected_exact<bool, null_function_t, SAX>::value && 9257 is_detected_exact<bool, boolean_function_t, SAX>::value && 9258 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value && 9259 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value && 9260 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value && 9261 is_detected_exact<bool, string_function_t, SAX, string_t>::value && 9262 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value && 9263 is_detected_exact<bool, start_object_function_t, SAX>::value && 9264 is_detected_exact<bool, key_function_t, SAX, string_t>::value && 9265 is_detected_exact<bool, end_object_function_t, SAX>::value && 9266 is_detected_exact<bool, start_array_function_t, SAX>::value && 9267 is_detected_exact<bool, end_array_function_t, SAX>::value && 9268 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value; 9269 }; 9270 9271 template<typename SAX, typename BasicJsonType> 9272 struct is_sax_static_asserts 9273 { 9274 private: 9275 static_assert(is_basic_json<BasicJsonType>::value, 9276 "BasicJsonType must be of type basic_json<...>"); 9277 9278 using number_integer_t = typename BasicJsonType::number_integer_t; 9279 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 9280 using number_float_t = typename BasicJsonType::number_float_t; 9281 using string_t = typename BasicJsonType::string_t; 9282 using binary_t = typename BasicJsonType::binary_t; 9283 using exception_t = typename BasicJsonType::exception; 9284 9285 public: 9286 static_assert(is_detected_exact<bool, null_function_t, SAX>::value, 9287 "Missing/invalid function: bool null()"); 9288 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value, 9289 "Missing/invalid function: bool boolean(bool)"); 9290 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value, 9291 "Missing/invalid function: bool boolean(bool)"); 9292 static_assert( 9293 is_detected_exact<bool, number_integer_function_t, SAX, 9294 number_integer_t>::value, 9295 "Missing/invalid function: bool number_integer(number_integer_t)"); 9296 static_assert( 9297 is_detected_exact<bool, number_unsigned_function_t, SAX, 9298 number_unsigned_t>::value, 9299 "Missing/invalid function: bool number_unsigned(number_unsigned_t)"); 9300 static_assert(is_detected_exact<bool, number_float_function_t, SAX, 9301 number_float_t, string_t>::value, 9302 "Missing/invalid function: bool number_float(number_float_t, const string_t&)"); 9303 static_assert( 9304 is_detected_exact<bool, string_function_t, SAX, string_t>::value, 9305 "Missing/invalid function: bool string(string_t&)"); 9306 static_assert( 9307 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value, 9308 "Missing/invalid function: bool binary(binary_t&)"); 9309 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value, 9310 "Missing/invalid function: bool start_object(std::size_t)"); 9311 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value, 9312 "Missing/invalid function: bool key(string_t&)"); 9313 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value, 9314 "Missing/invalid function: bool end_object()"); 9315 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value, 9316 "Missing/invalid function: bool start_array(std::size_t)"); 9317 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value, 9318 "Missing/invalid function: bool end_array()"); 9319 static_assert( 9320 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value, 9321 "Missing/invalid function: bool parse_error(std::size_t, const " 9322 "std::string&, const exception&)"); 9323 }; 9324 9325 } // namespace detail 9326 NLOHMANN_JSON_NAMESPACE_END 9327 9328 // #include <nlohmann/detail/meta/type_traits.hpp> 9329 9330 // #include <nlohmann/detail/string_concat.hpp> 9331 9332 // #include <nlohmann/detail/value_t.hpp> 9333 9334 9335 NLOHMANN_JSON_NAMESPACE_BEGIN 9336 namespace detail 9337 { 9338 9339 /// how to treat CBOR tags 9340 enum class cbor_tag_handler_t 9341 { 9342 error, ///< throw a parse_error exception in case of a tag 9343 ignore, ///< ignore tags 9344 store ///< store tags as binary type 9345 }; 9346 9347 /*! 9348 @brief determine system byte order 9349 9350 @return true if and only if system's byte order is little endian 9351 9352 @note from https://stackoverflow.com/a/1001328/266378 9353 */ 9354 static inline bool little_endianness(int num = 1) noexcept 9355 { 9356 return *reinterpret_cast<char*>(&num) == 1; 9357 } 9358 9359 /////////////////// 9360 // binary reader // 9361 /////////////////// 9362 9363 /*! 9364 @brief deserialization of CBOR, MessagePack, and UBJSON values 9365 */ 9366 template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>> 9367 class binary_reader 9368 { 9369 using number_integer_t = typename BasicJsonType::number_integer_t; 9370 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 9371 using number_float_t = typename BasicJsonType::number_float_t; 9372 using string_t = typename BasicJsonType::string_t; 9373 using binary_t = typename BasicJsonType::binary_t; 9374 using json_sax_t = SAX; 9375 using char_type = typename InputAdapterType::char_type; 9376 using char_int_type = typename char_traits<char_type>::int_type; 9377 9378 public: 9379 /*! 9380 @brief create a binary reader 9381 9382 @param[in] adapter input adapter to read from 9383 */ 9384 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format) 9385 { 9386 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {}; 9387 } 9388 9389 // make class move-only 9390 binary_reader(const binary_reader&) = delete; 9391 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 9392 binary_reader& operator=(const binary_reader&) = delete; 9393 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 9394 ~binary_reader() = default; 9395 9396 /*! 9397 @param[in] format the binary format to parse 9398 @param[in] sax_ a SAX event processor 9399 @param[in] strict whether to expect the input to be consumed completed 9400 @param[in] tag_handler how to treat CBOR tags 9401 9402 @return whether parsing was successful 9403 */ 9404 JSON_HEDLEY_NON_NULL(3) 9405 bool sax_parse(const input_format_t format, 9406 json_sax_t* sax_, 9407 const bool strict = true, 9408 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 9409 { 9410 sax = sax_; 9411 bool result = false; 9412 9413 switch (format) 9414 { 9415 case input_format_t::bson: 9416 result = parse_bson_internal(); 9417 break; 9418 9419 case input_format_t::cbor: 9420 result = parse_cbor_internal(true, tag_handler); 9421 break; 9422 9423 case input_format_t::msgpack: 9424 result = parse_msgpack_internal(); 9425 break; 9426 9427 case input_format_t::ubjson: 9428 case input_format_t::bjdata: 9429 result = parse_ubjson_internal(); 9430 break; 9431 9432 case input_format_t::json: // LCOV_EXCL_LINE 9433 default: // LCOV_EXCL_LINE 9434 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 9435 } 9436 9437 // strict mode: next byte must be EOF 9438 if (result && strict) 9439 { 9440 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata) 9441 { 9442 get_ignore_noop(); 9443 } 9444 else 9445 { 9446 get(); 9447 } 9448 9449 if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof())) 9450 { 9451 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, 9452 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr)); 9453 } 9454 } 9455 9456 return result; 9457 } 9458 9459 private: 9460 ////////// 9461 // BSON // 9462 ////////// 9463 9464 /*! 9465 @brief Reads in a BSON-object and passes it to the SAX-parser. 9466 @return whether a valid BSON-value was passed to the SAX parser 9467 */ 9468 bool parse_bson_internal() 9469 { 9470 std::int32_t document_size{}; 9471 get_number<std::int32_t, true>(input_format_t::bson, document_size); 9472 9473 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) 9474 { 9475 return false; 9476 } 9477 9478 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false))) 9479 { 9480 return false; 9481 } 9482 9483 return sax->end_object(); 9484 } 9485 9486 /*! 9487 @brief Parses a C-style string from the BSON input. 9488 @param[in,out] result A reference to the string variable where the read 9489 string is to be stored. 9490 @return `true` if the \x00-byte indicating the end of the string was 9491 encountered before the EOF; false` indicates an unexpected EOF. 9492 */ 9493 bool get_bson_cstr(string_t& result) 9494 { 9495 auto out = std::back_inserter(result); 9496 while (true) 9497 { 9498 get(); 9499 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) 9500 { 9501 return false; 9502 } 9503 if (current == 0x00) 9504 { 9505 return true; 9506 } 9507 *out++ = static_cast<typename string_t::value_type>(current); 9508 } 9509 } 9510 9511 /*! 9512 @brief Parses a zero-terminated string of length @a len from the BSON 9513 input. 9514 @param[in] len The length (including the zero-byte at the end) of the 9515 string to be read. 9516 @param[in,out] result A reference to the string variable where the read 9517 string is to be stored. 9518 @tparam NumberType The type of the length @a len 9519 @pre len >= 1 9520 @return `true` if the string was successfully parsed 9521 */ 9522 template<typename NumberType> 9523 bool get_bson_string(const NumberType len, string_t& result) 9524 { 9525 if (JSON_HEDLEY_UNLIKELY(len < 1)) 9526 { 9527 auto last_token = get_token_string(); 9528 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 9529 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr)); 9530 } 9531 9532 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof(); 9533 } 9534 9535 /*! 9536 @brief Parses a byte array input of length @a len from the BSON input. 9537 @param[in] len The length of the byte array to be read. 9538 @param[in,out] result A reference to the binary variable where the read 9539 array is to be stored. 9540 @tparam NumberType The type of the length @a len 9541 @pre len >= 0 9542 @return `true` if the byte array was successfully parsed 9543 */ 9544 template<typename NumberType> 9545 bool get_bson_binary(const NumberType len, binary_t& result) 9546 { 9547 if (JSON_HEDLEY_UNLIKELY(len < 0)) 9548 { 9549 auto last_token = get_token_string(); 9550 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 9551 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr)); 9552 } 9553 9554 // All BSON binary values have a subtype 9555 std::uint8_t subtype{}; 9556 get_number<std::uint8_t>(input_format_t::bson, subtype); 9557 result.set_subtype(subtype); 9558 9559 return get_binary(input_format_t::bson, len, result); 9560 } 9561 9562 /*! 9563 @brief Read a BSON document element of the given @a element_type. 9564 @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html 9565 @param[in] element_type_parse_position The position in the input stream, 9566 where the `element_type` was read. 9567 @warning Not all BSON element types are supported yet. An unsupported 9568 @a element_type will give rise to a parse_error.114: 9569 Unsupported BSON record type 0x... 9570 @return whether a valid BSON-object/array was passed to the SAX parser 9571 */ 9572 bool parse_bson_element_internal(const char_int_type element_type, 9573 const std::size_t element_type_parse_position) 9574 { 9575 switch (element_type) 9576 { 9577 case 0x01: // double 9578 { 9579 double number{}; 9580 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), ""); 9581 } 9582 9583 case 0x02: // string 9584 { 9585 std::int32_t len{}; 9586 string_t value; 9587 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value); 9588 } 9589 9590 case 0x03: // object 9591 { 9592 return parse_bson_internal(); 9593 } 9594 9595 case 0x04: // array 9596 { 9597 return parse_bson_array(); 9598 } 9599 9600 case 0x05: // binary 9601 { 9602 std::int32_t len{}; 9603 binary_t value; 9604 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value); 9605 } 9606 9607 case 0x08: // boolean 9608 { 9609 return sax->boolean(get() != 0); 9610 } 9611 9612 case 0x0A: // null 9613 { 9614 return sax->null(); 9615 } 9616 9617 case 0x10: // int32 9618 { 9619 std::int32_t value{}; 9620 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value); 9621 } 9622 9623 case 0x12: // int64 9624 { 9625 std::int64_t value{}; 9626 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value); 9627 } 9628 9629 default: // anything else not supported (yet) 9630 { 9631 std::array<char, 3> cr{{}}; 9632 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 9633 const std::string cr_str{cr.data()}; 9634 return sax->parse_error(element_type_parse_position, cr_str, 9635 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr)); 9636 } 9637 } 9638 } 9639 9640 /*! 9641 @brief Read a BSON element list (as specified in the BSON-spec) 9642 9643 The same binary layout is used for objects and arrays, hence it must be 9644 indicated with the argument @a is_array which one is expected 9645 (true --> array, false --> object). 9646 9647 @param[in] is_array Determines if the element list being read is to be 9648 treated as an object (@a is_array == false), or as an 9649 array (@a is_array == true). 9650 @return whether a valid BSON-object/array was passed to the SAX parser 9651 */ 9652 bool parse_bson_element_list(const bool is_array) 9653 { 9654 string_t key; 9655 9656 while (auto element_type = get()) 9657 { 9658 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) 9659 { 9660 return false; 9661 } 9662 9663 const std::size_t element_type_parse_position = chars_read; 9664 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) 9665 { 9666 return false; 9667 } 9668 9669 if (!is_array && !sax->key(key)) 9670 { 9671 return false; 9672 } 9673 9674 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position))) 9675 { 9676 return false; 9677 } 9678 9679 // get_bson_cstr only appends 9680 key.clear(); 9681 } 9682 9683 return true; 9684 } 9685 9686 /*! 9687 @brief Reads an array from the BSON input and passes it to the SAX-parser. 9688 @return whether a valid BSON-array was passed to the SAX parser 9689 */ 9690 bool parse_bson_array() 9691 { 9692 std::int32_t document_size{}; 9693 get_number<std::int32_t, true>(input_format_t::bson, document_size); 9694 9695 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) 9696 { 9697 return false; 9698 } 9699 9700 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true))) 9701 { 9702 return false; 9703 } 9704 9705 return sax->end_array(); 9706 } 9707 9708 ////////// 9709 // CBOR // 9710 ////////// 9711 9712 /*! 9713 @param[in] get_char whether a new character should be retrieved from the 9714 input (true) or whether the last read character should 9715 be considered instead (false) 9716 @param[in] tag_handler how CBOR tags should be treated 9717 9718 @return whether a valid CBOR value was passed to the SAX parser 9719 */ 9720 bool parse_cbor_internal(const bool get_char, 9721 const cbor_tag_handler_t tag_handler) 9722 { 9723 switch (get_char ? get() : current) 9724 { 9725 // EOF 9726 case char_traits<char_type>::eof(): 9727 return unexpect_eof(input_format_t::cbor, "value"); 9728 9729 // Integer 0x00..0x17 (0..23) 9730 case 0x00: 9731 case 0x01: 9732 case 0x02: 9733 case 0x03: 9734 case 0x04: 9735 case 0x05: 9736 case 0x06: 9737 case 0x07: 9738 case 0x08: 9739 case 0x09: 9740 case 0x0A: 9741 case 0x0B: 9742 case 0x0C: 9743 case 0x0D: 9744 case 0x0E: 9745 case 0x0F: 9746 case 0x10: 9747 case 0x11: 9748 case 0x12: 9749 case 0x13: 9750 case 0x14: 9751 case 0x15: 9752 case 0x16: 9753 case 0x17: 9754 return sax->number_unsigned(static_cast<number_unsigned_t>(current)); 9755 9756 case 0x18: // Unsigned integer (one-byte uint8_t follows) 9757 { 9758 std::uint8_t number{}; 9759 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); 9760 } 9761 9762 case 0x19: // Unsigned integer (two-byte uint16_t follows) 9763 { 9764 std::uint16_t number{}; 9765 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); 9766 } 9767 9768 case 0x1A: // Unsigned integer (four-byte uint32_t follows) 9769 { 9770 std::uint32_t number{}; 9771 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); 9772 } 9773 9774 case 0x1B: // Unsigned integer (eight-byte uint64_t follows) 9775 { 9776 std::uint64_t number{}; 9777 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); 9778 } 9779 9780 // Negative integer -1-0x00..-1-0x17 (-1..-24) 9781 case 0x20: 9782 case 0x21: 9783 case 0x22: 9784 case 0x23: 9785 case 0x24: 9786 case 0x25: 9787 case 0x26: 9788 case 0x27: 9789 case 0x28: 9790 case 0x29: 9791 case 0x2A: 9792 case 0x2B: 9793 case 0x2C: 9794 case 0x2D: 9795 case 0x2E: 9796 case 0x2F: 9797 case 0x30: 9798 case 0x31: 9799 case 0x32: 9800 case 0x33: 9801 case 0x34: 9802 case 0x35: 9803 case 0x36: 9804 case 0x37: 9805 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current)); 9806 9807 case 0x38: // Negative integer (one-byte uint8_t follows) 9808 { 9809 std::uint8_t number{}; 9810 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number); 9811 } 9812 9813 case 0x39: // Negative integer -1-n (two-byte uint16_t follows) 9814 { 9815 std::uint16_t number{}; 9816 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number); 9817 } 9818 9819 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) 9820 { 9821 std::uint32_t number{}; 9822 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number); 9823 } 9824 9825 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) 9826 { 9827 std::uint64_t number{}; 9828 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) 9829 - static_cast<number_integer_t>(number)); 9830 } 9831 9832 // Binary data (0x00..0x17 bytes follow) 9833 case 0x40: 9834 case 0x41: 9835 case 0x42: 9836 case 0x43: 9837 case 0x44: 9838 case 0x45: 9839 case 0x46: 9840 case 0x47: 9841 case 0x48: 9842 case 0x49: 9843 case 0x4A: 9844 case 0x4B: 9845 case 0x4C: 9846 case 0x4D: 9847 case 0x4E: 9848 case 0x4F: 9849 case 0x50: 9850 case 0x51: 9851 case 0x52: 9852 case 0x53: 9853 case 0x54: 9854 case 0x55: 9855 case 0x56: 9856 case 0x57: 9857 case 0x58: // Binary data (one-byte uint8_t for n follows) 9858 case 0x59: // Binary data (two-byte uint16_t for n follow) 9859 case 0x5A: // Binary data (four-byte uint32_t for n follow) 9860 case 0x5B: // Binary data (eight-byte uint64_t for n follow) 9861 case 0x5F: // Binary data (indefinite length) 9862 { 9863 binary_t b; 9864 return get_cbor_binary(b) && sax->binary(b); 9865 } 9866 9867 // UTF-8 string (0x00..0x17 bytes follow) 9868 case 0x60: 9869 case 0x61: 9870 case 0x62: 9871 case 0x63: 9872 case 0x64: 9873 case 0x65: 9874 case 0x66: 9875 case 0x67: 9876 case 0x68: 9877 case 0x69: 9878 case 0x6A: 9879 case 0x6B: 9880 case 0x6C: 9881 case 0x6D: 9882 case 0x6E: 9883 case 0x6F: 9884 case 0x70: 9885 case 0x71: 9886 case 0x72: 9887 case 0x73: 9888 case 0x74: 9889 case 0x75: 9890 case 0x76: 9891 case 0x77: 9892 case 0x78: // UTF-8 string (one-byte uint8_t for n follows) 9893 case 0x79: // UTF-8 string (two-byte uint16_t for n follow) 9894 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) 9895 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) 9896 case 0x7F: // UTF-8 string (indefinite length) 9897 { 9898 string_t s; 9899 return get_cbor_string(s) && sax->string(s); 9900 } 9901 9902 // array (0x00..0x17 data items follow) 9903 case 0x80: 9904 case 0x81: 9905 case 0x82: 9906 case 0x83: 9907 case 0x84: 9908 case 0x85: 9909 case 0x86: 9910 case 0x87: 9911 case 0x88: 9912 case 0x89: 9913 case 0x8A: 9914 case 0x8B: 9915 case 0x8C: 9916 case 0x8D: 9917 case 0x8E: 9918 case 0x8F: 9919 case 0x90: 9920 case 0x91: 9921 case 0x92: 9922 case 0x93: 9923 case 0x94: 9924 case 0x95: 9925 case 0x96: 9926 case 0x97: 9927 return get_cbor_array( 9928 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler); 9929 9930 case 0x98: // array (one-byte uint8_t for n follows) 9931 { 9932 std::uint8_t len{}; 9933 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler); 9934 } 9935 9936 case 0x99: // array (two-byte uint16_t for n follow) 9937 { 9938 std::uint16_t len{}; 9939 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler); 9940 } 9941 9942 case 0x9A: // array (four-byte uint32_t for n follow) 9943 { 9944 std::uint32_t len{}; 9945 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler); 9946 } 9947 9948 case 0x9B: // array (eight-byte uint64_t for n follow) 9949 { 9950 std::uint64_t len{}; 9951 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler); 9952 } 9953 9954 case 0x9F: // array (indefinite length) 9955 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler); 9956 9957 // map (0x00..0x17 pairs of data items follow) 9958 case 0xA0: 9959 case 0xA1: 9960 case 0xA2: 9961 case 0xA3: 9962 case 0xA4: 9963 case 0xA5: 9964 case 0xA6: 9965 case 0xA7: 9966 case 0xA8: 9967 case 0xA9: 9968 case 0xAA: 9969 case 0xAB: 9970 case 0xAC: 9971 case 0xAD: 9972 case 0xAE: 9973 case 0xAF: 9974 case 0xB0: 9975 case 0xB1: 9976 case 0xB2: 9977 case 0xB3: 9978 case 0xB4: 9979 case 0xB5: 9980 case 0xB6: 9981 case 0xB7: 9982 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler); 9983 9984 case 0xB8: // map (one-byte uint8_t for n follows) 9985 { 9986 std::uint8_t len{}; 9987 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler); 9988 } 9989 9990 case 0xB9: // map (two-byte uint16_t for n follow) 9991 { 9992 std::uint16_t len{}; 9993 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler); 9994 } 9995 9996 case 0xBA: // map (four-byte uint32_t for n follow) 9997 { 9998 std::uint32_t len{}; 9999 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler); 10000 } 10001 10002 case 0xBB: // map (eight-byte uint64_t for n follow) 10003 { 10004 std::uint64_t len{}; 10005 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler); 10006 } 10007 10008 case 0xBF: // map (indefinite length) 10009 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler); 10010 10011 case 0xC6: // tagged item 10012 case 0xC7: 10013 case 0xC8: 10014 case 0xC9: 10015 case 0xCA: 10016 case 0xCB: 10017 case 0xCC: 10018 case 0xCD: 10019 case 0xCE: 10020 case 0xCF: 10021 case 0xD0: 10022 case 0xD1: 10023 case 0xD2: 10024 case 0xD3: 10025 case 0xD4: 10026 case 0xD8: // tagged item (1 bytes follow) 10027 case 0xD9: // tagged item (2 bytes follow) 10028 case 0xDA: // tagged item (4 bytes follow) 10029 case 0xDB: // tagged item (8 bytes follow) 10030 { 10031 switch (tag_handler) 10032 { 10033 case cbor_tag_handler_t::error: 10034 { 10035 auto last_token = get_token_string(); 10036 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 10037 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr)); 10038 } 10039 10040 case cbor_tag_handler_t::ignore: 10041 { 10042 // ignore binary subtype 10043 switch (current) 10044 { 10045 case 0xD8: 10046 { 10047 std::uint8_t subtype_to_ignore{}; 10048 get_number(input_format_t::cbor, subtype_to_ignore); 10049 break; 10050 } 10051 case 0xD9: 10052 { 10053 std::uint16_t subtype_to_ignore{}; 10054 get_number(input_format_t::cbor, subtype_to_ignore); 10055 break; 10056 } 10057 case 0xDA: 10058 { 10059 std::uint32_t subtype_to_ignore{}; 10060 get_number(input_format_t::cbor, subtype_to_ignore); 10061 break; 10062 } 10063 case 0xDB: 10064 { 10065 std::uint64_t subtype_to_ignore{}; 10066 get_number(input_format_t::cbor, subtype_to_ignore); 10067 break; 10068 } 10069 default: 10070 break; 10071 } 10072 return parse_cbor_internal(true, tag_handler); 10073 } 10074 10075 case cbor_tag_handler_t::store: 10076 { 10077 binary_t b; 10078 // use binary subtype and store in binary container 10079 switch (current) 10080 { 10081 case 0xD8: 10082 { 10083 std::uint8_t subtype{}; 10084 get_number(input_format_t::cbor, subtype); 10085 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype)); 10086 break; 10087 } 10088 case 0xD9: 10089 { 10090 std::uint16_t subtype{}; 10091 get_number(input_format_t::cbor, subtype); 10092 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype)); 10093 break; 10094 } 10095 case 0xDA: 10096 { 10097 std::uint32_t subtype{}; 10098 get_number(input_format_t::cbor, subtype); 10099 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype)); 10100 break; 10101 } 10102 case 0xDB: 10103 { 10104 std::uint64_t subtype{}; 10105 get_number(input_format_t::cbor, subtype); 10106 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype)); 10107 break; 10108 } 10109 default: 10110 return parse_cbor_internal(true, tag_handler); 10111 } 10112 get(); 10113 return get_cbor_binary(b) && sax->binary(b); 10114 } 10115 10116 default: // LCOV_EXCL_LINE 10117 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 10118 return false; // LCOV_EXCL_LINE 10119 } 10120 } 10121 10122 case 0xF4: // false 10123 return sax->boolean(false); 10124 10125 case 0xF5: // true 10126 return sax->boolean(true); 10127 10128 case 0xF6: // null 10129 return sax->null(); 10130 10131 case 0xF9: // Half-Precision Float (two-byte IEEE 754) 10132 { 10133 const auto byte1_raw = get(); 10134 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) 10135 { 10136 return false; 10137 } 10138 const auto byte2_raw = get(); 10139 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) 10140 { 10141 return false; 10142 } 10143 10144 const auto byte1 = static_cast<unsigned char>(byte1_raw); 10145 const auto byte2 = static_cast<unsigned char>(byte2_raw); 10146 10147 // code from RFC 7049, Appendix D, Figure 3: 10148 // As half-precision floating-point numbers were only added 10149 // to IEEE 754 in 2008, today's programming platforms often 10150 // still only have limited support for them. It is very 10151 // easy to include at least decoding support for them even 10152 // without such support. An example of a small decoder for 10153 // half-precision floating-point numbers in the C language 10154 // is shown in Fig. 3. 10155 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2); 10156 const double val = [&half] 10157 { 10158 const int exp = (half >> 10u) & 0x1Fu; 10159 const unsigned int mant = half & 0x3FFu; 10160 JSON_ASSERT(0 <= exp&& exp <= 32); 10161 JSON_ASSERT(mant <= 1024); 10162 switch (exp) 10163 { 10164 case 0: 10165 return std::ldexp(mant, -24); 10166 case 31: 10167 return (mant == 0) 10168 ? std::numeric_limits<double>::infinity() 10169 : std::numeric_limits<double>::quiet_NaN(); 10170 default: 10171 return std::ldexp(mant + 1024, exp - 25); 10172 } 10173 }(); 10174 return sax->number_float((half & 0x8000u) != 0 10175 ? static_cast<number_float_t>(-val) 10176 : static_cast<number_float_t>(val), ""); 10177 } 10178 10179 case 0xFA: // Single-Precision Float (four-byte IEEE 754) 10180 { 10181 float number{}; 10182 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), ""); 10183 } 10184 10185 case 0xFB: // Double-Precision Float (eight-byte IEEE 754) 10186 { 10187 double number{}; 10188 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), ""); 10189 } 10190 10191 default: // anything else (0xFF is handled inside the other types) 10192 { 10193 auto last_token = get_token_string(); 10194 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 10195 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr)); 10196 } 10197 } 10198 } 10199 10200 /*! 10201 @brief reads a CBOR string 10202 10203 This function first reads starting bytes to determine the expected 10204 string length and then copies this number of bytes into a string. 10205 Additionally, CBOR's strings with indefinite lengths are supported. 10206 10207 @param[out] result created string 10208 10209 @return whether string creation completed 10210 */ 10211 bool get_cbor_string(string_t& result) 10212 { 10213 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) 10214 { 10215 return false; 10216 } 10217 10218 switch (current) 10219 { 10220 // UTF-8 string (0x00..0x17 bytes follow) 10221 case 0x60: 10222 case 0x61: 10223 case 0x62: 10224 case 0x63: 10225 case 0x64: 10226 case 0x65: 10227 case 0x66: 10228 case 0x67: 10229 case 0x68: 10230 case 0x69: 10231 case 0x6A: 10232 case 0x6B: 10233 case 0x6C: 10234 case 0x6D: 10235 case 0x6E: 10236 case 0x6F: 10237 case 0x70: 10238 case 0x71: 10239 case 0x72: 10240 case 0x73: 10241 case 0x74: 10242 case 0x75: 10243 case 0x76: 10244 case 0x77: 10245 { 10246 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result); 10247 } 10248 10249 case 0x78: // UTF-8 string (one-byte uint8_t for n follows) 10250 { 10251 std::uint8_t len{}; 10252 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); 10253 } 10254 10255 case 0x79: // UTF-8 string (two-byte uint16_t for n follow) 10256 { 10257 std::uint16_t len{}; 10258 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); 10259 } 10260 10261 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) 10262 { 10263 std::uint32_t len{}; 10264 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); 10265 } 10266 10267 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) 10268 { 10269 std::uint64_t len{}; 10270 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); 10271 } 10272 10273 case 0x7F: // UTF-8 string (indefinite length) 10274 { 10275 while (get() != 0xFF) 10276 { 10277 string_t chunk; 10278 if (!get_cbor_string(chunk)) 10279 { 10280 return false; 10281 } 10282 result.append(chunk); 10283 } 10284 return true; 10285 } 10286 10287 default: 10288 { 10289 auto last_token = get_token_string(); 10290 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, 10291 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr)); 10292 } 10293 } 10294 } 10295 10296 /*! 10297 @brief reads a CBOR byte array 10298 10299 This function first reads starting bytes to determine the expected 10300 byte array length and then copies this number of bytes into the byte array. 10301 Additionally, CBOR's byte arrays with indefinite lengths are supported. 10302 10303 @param[out] result created byte array 10304 10305 @return whether byte array creation completed 10306 */ 10307 bool get_cbor_binary(binary_t& result) 10308 { 10309 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) 10310 { 10311 return false; 10312 } 10313 10314 switch (current) 10315 { 10316 // Binary data (0x00..0x17 bytes follow) 10317 case 0x40: 10318 case 0x41: 10319 case 0x42: 10320 case 0x43: 10321 case 0x44: 10322 case 0x45: 10323 case 0x46: 10324 case 0x47: 10325 case 0x48: 10326 case 0x49: 10327 case 0x4A: 10328 case 0x4B: 10329 case 0x4C: 10330 case 0x4D: 10331 case 0x4E: 10332 case 0x4F: 10333 case 0x50: 10334 case 0x51: 10335 case 0x52: 10336 case 0x53: 10337 case 0x54: 10338 case 0x55: 10339 case 0x56: 10340 case 0x57: 10341 { 10342 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result); 10343 } 10344 10345 case 0x58: // Binary data (one-byte uint8_t for n follows) 10346 { 10347 std::uint8_t len{}; 10348 return get_number(input_format_t::cbor, len) && 10349 get_binary(input_format_t::cbor, len, result); 10350 } 10351 10352 case 0x59: // Binary data (two-byte uint16_t for n follow) 10353 { 10354 std::uint16_t len{}; 10355 return get_number(input_format_t::cbor, len) && 10356 get_binary(input_format_t::cbor, len, result); 10357 } 10358 10359 case 0x5A: // Binary data (four-byte uint32_t for n follow) 10360 { 10361 std::uint32_t len{}; 10362 return get_number(input_format_t::cbor, len) && 10363 get_binary(input_format_t::cbor, len, result); 10364 } 10365 10366 case 0x5B: // Binary data (eight-byte uint64_t for n follow) 10367 { 10368 std::uint64_t len{}; 10369 return get_number(input_format_t::cbor, len) && 10370 get_binary(input_format_t::cbor, len, result); 10371 } 10372 10373 case 0x5F: // Binary data (indefinite length) 10374 { 10375 while (get() != 0xFF) 10376 { 10377 binary_t chunk; 10378 if (!get_cbor_binary(chunk)) 10379 { 10380 return false; 10381 } 10382 result.insert(result.end(), chunk.begin(), chunk.end()); 10383 } 10384 return true; 10385 } 10386 10387 default: 10388 { 10389 auto last_token = get_token_string(); 10390 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, 10391 exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr)); 10392 } 10393 } 10394 } 10395 10396 /*! 10397 @param[in] len the length of the array or static_cast<std::size_t>(-1) for an 10398 array of indefinite size 10399 @param[in] tag_handler how CBOR tags should be treated 10400 @return whether array creation completed 10401 */ 10402 bool get_cbor_array(const std::size_t len, 10403 const cbor_tag_handler_t tag_handler) 10404 { 10405 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) 10406 { 10407 return false; 10408 } 10409 10410 if (len != static_cast<std::size_t>(-1)) 10411 { 10412 for (std::size_t i = 0; i < len; ++i) 10413 { 10414 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) 10415 { 10416 return false; 10417 } 10418 } 10419 } 10420 else 10421 { 10422 while (get() != 0xFF) 10423 { 10424 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) 10425 { 10426 return false; 10427 } 10428 } 10429 } 10430 10431 return sax->end_array(); 10432 } 10433 10434 /*! 10435 @param[in] len the length of the object or static_cast<std::size_t>(-1) for an 10436 object of indefinite size 10437 @param[in] tag_handler how CBOR tags should be treated 10438 @return whether object creation completed 10439 */ 10440 bool get_cbor_object(const std::size_t len, 10441 const cbor_tag_handler_t tag_handler) 10442 { 10443 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) 10444 { 10445 return false; 10446 } 10447 10448 if (len != 0) 10449 { 10450 string_t key; 10451 if (len != static_cast<std::size_t>(-1)) 10452 { 10453 for (std::size_t i = 0; i < len; ++i) 10454 { 10455 get(); 10456 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) 10457 { 10458 return false; 10459 } 10460 10461 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) 10462 { 10463 return false; 10464 } 10465 key.clear(); 10466 } 10467 } 10468 else 10469 { 10470 while (get() != 0xFF) 10471 { 10472 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) 10473 { 10474 return false; 10475 } 10476 10477 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) 10478 { 10479 return false; 10480 } 10481 key.clear(); 10482 } 10483 } 10484 } 10485 10486 return sax->end_object(); 10487 } 10488 10489 ///////////// 10490 // MsgPack // 10491 ///////////// 10492 10493 /*! 10494 @return whether a valid MessagePack value was passed to the SAX parser 10495 */ 10496 bool parse_msgpack_internal() 10497 { 10498 switch (get()) 10499 { 10500 // EOF 10501 case char_traits<char_type>::eof(): 10502 return unexpect_eof(input_format_t::msgpack, "value"); 10503 10504 // positive fixint 10505 case 0x00: 10506 case 0x01: 10507 case 0x02: 10508 case 0x03: 10509 case 0x04: 10510 case 0x05: 10511 case 0x06: 10512 case 0x07: 10513 case 0x08: 10514 case 0x09: 10515 case 0x0A: 10516 case 0x0B: 10517 case 0x0C: 10518 case 0x0D: 10519 case 0x0E: 10520 case 0x0F: 10521 case 0x10: 10522 case 0x11: 10523 case 0x12: 10524 case 0x13: 10525 case 0x14: 10526 case 0x15: 10527 case 0x16: 10528 case 0x17: 10529 case 0x18: 10530 case 0x19: 10531 case 0x1A: 10532 case 0x1B: 10533 case 0x1C: 10534 case 0x1D: 10535 case 0x1E: 10536 case 0x1F: 10537 case 0x20: 10538 case 0x21: 10539 case 0x22: 10540 case 0x23: 10541 case 0x24: 10542 case 0x25: 10543 case 0x26: 10544 case 0x27: 10545 case 0x28: 10546 case 0x29: 10547 case 0x2A: 10548 case 0x2B: 10549 case 0x2C: 10550 case 0x2D: 10551 case 0x2E: 10552 case 0x2F: 10553 case 0x30: 10554 case 0x31: 10555 case 0x32: 10556 case 0x33: 10557 case 0x34: 10558 case 0x35: 10559 case 0x36: 10560 case 0x37: 10561 case 0x38: 10562 case 0x39: 10563 case 0x3A: 10564 case 0x3B: 10565 case 0x3C: 10566 case 0x3D: 10567 case 0x3E: 10568 case 0x3F: 10569 case 0x40: 10570 case 0x41: 10571 case 0x42: 10572 case 0x43: 10573 case 0x44: 10574 case 0x45: 10575 case 0x46: 10576 case 0x47: 10577 case 0x48: 10578 case 0x49: 10579 case 0x4A: 10580 case 0x4B: 10581 case 0x4C: 10582 case 0x4D: 10583 case 0x4E: 10584 case 0x4F: 10585 case 0x50: 10586 case 0x51: 10587 case 0x52: 10588 case 0x53: 10589 case 0x54: 10590 case 0x55: 10591 case 0x56: 10592 case 0x57: 10593 case 0x58: 10594 case 0x59: 10595 case 0x5A: 10596 case 0x5B: 10597 case 0x5C: 10598 case 0x5D: 10599 case 0x5E: 10600 case 0x5F: 10601 case 0x60: 10602 case 0x61: 10603 case 0x62: 10604 case 0x63: 10605 case 0x64: 10606 case 0x65: 10607 case 0x66: 10608 case 0x67: 10609 case 0x68: 10610 case 0x69: 10611 case 0x6A: 10612 case 0x6B: 10613 case 0x6C: 10614 case 0x6D: 10615 case 0x6E: 10616 case 0x6F: 10617 case 0x70: 10618 case 0x71: 10619 case 0x72: 10620 case 0x73: 10621 case 0x74: 10622 case 0x75: 10623 case 0x76: 10624 case 0x77: 10625 case 0x78: 10626 case 0x79: 10627 case 0x7A: 10628 case 0x7B: 10629 case 0x7C: 10630 case 0x7D: 10631 case 0x7E: 10632 case 0x7F: 10633 return sax->number_unsigned(static_cast<number_unsigned_t>(current)); 10634 10635 // fixmap 10636 case 0x80: 10637 case 0x81: 10638 case 0x82: 10639 case 0x83: 10640 case 0x84: 10641 case 0x85: 10642 case 0x86: 10643 case 0x87: 10644 case 0x88: 10645 case 0x89: 10646 case 0x8A: 10647 case 0x8B: 10648 case 0x8C: 10649 case 0x8D: 10650 case 0x8E: 10651 case 0x8F: 10652 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu)); 10653 10654 // fixarray 10655 case 0x90: 10656 case 0x91: 10657 case 0x92: 10658 case 0x93: 10659 case 0x94: 10660 case 0x95: 10661 case 0x96: 10662 case 0x97: 10663 case 0x98: 10664 case 0x99: 10665 case 0x9A: 10666 case 0x9B: 10667 case 0x9C: 10668 case 0x9D: 10669 case 0x9E: 10670 case 0x9F: 10671 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu)); 10672 10673 // fixstr 10674 case 0xA0: 10675 case 0xA1: 10676 case 0xA2: 10677 case 0xA3: 10678 case 0xA4: 10679 case 0xA5: 10680 case 0xA6: 10681 case 0xA7: 10682 case 0xA8: 10683 case 0xA9: 10684 case 0xAA: 10685 case 0xAB: 10686 case 0xAC: 10687 case 0xAD: 10688 case 0xAE: 10689 case 0xAF: 10690 case 0xB0: 10691 case 0xB1: 10692 case 0xB2: 10693 case 0xB3: 10694 case 0xB4: 10695 case 0xB5: 10696 case 0xB6: 10697 case 0xB7: 10698 case 0xB8: 10699 case 0xB9: 10700 case 0xBA: 10701 case 0xBB: 10702 case 0xBC: 10703 case 0xBD: 10704 case 0xBE: 10705 case 0xBF: 10706 case 0xD9: // str 8 10707 case 0xDA: // str 16 10708 case 0xDB: // str 32 10709 { 10710 string_t s; 10711 return get_msgpack_string(s) && sax->string(s); 10712 } 10713 10714 case 0xC0: // nil 10715 return sax->null(); 10716 10717 case 0xC2: // false 10718 return sax->boolean(false); 10719 10720 case 0xC3: // true 10721 return sax->boolean(true); 10722 10723 case 0xC4: // bin 8 10724 case 0xC5: // bin 16 10725 case 0xC6: // bin 32 10726 case 0xC7: // ext 8 10727 case 0xC8: // ext 16 10728 case 0xC9: // ext 32 10729 case 0xD4: // fixext 1 10730 case 0xD5: // fixext 2 10731 case 0xD6: // fixext 4 10732 case 0xD7: // fixext 8 10733 case 0xD8: // fixext 16 10734 { 10735 binary_t b; 10736 return get_msgpack_binary(b) && sax->binary(b); 10737 } 10738 10739 case 0xCA: // float 32 10740 { 10741 float number{}; 10742 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), ""); 10743 } 10744 10745 case 0xCB: // float 64 10746 { 10747 double number{}; 10748 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), ""); 10749 } 10750 10751 case 0xCC: // uint 8 10752 { 10753 std::uint8_t number{}; 10754 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); 10755 } 10756 10757 case 0xCD: // uint 16 10758 { 10759 std::uint16_t number{}; 10760 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); 10761 } 10762 10763 case 0xCE: // uint 32 10764 { 10765 std::uint32_t number{}; 10766 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); 10767 } 10768 10769 case 0xCF: // uint 64 10770 { 10771 std::uint64_t number{}; 10772 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); 10773 } 10774 10775 case 0xD0: // int 8 10776 { 10777 std::int8_t number{}; 10778 return get_number(input_format_t::msgpack, number) && sax->number_integer(number); 10779 } 10780 10781 case 0xD1: // int 16 10782 { 10783 std::int16_t number{}; 10784 return get_number(input_format_t::msgpack, number) && sax->number_integer(number); 10785 } 10786 10787 case 0xD2: // int 32 10788 { 10789 std::int32_t number{}; 10790 return get_number(input_format_t::msgpack, number) && sax->number_integer(number); 10791 } 10792 10793 case 0xD3: // int 64 10794 { 10795 std::int64_t number{}; 10796 return get_number(input_format_t::msgpack, number) && sax->number_integer(number); 10797 } 10798 10799 case 0xDC: // array 16 10800 { 10801 std::uint16_t len{}; 10802 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len)); 10803 } 10804 10805 case 0xDD: // array 32 10806 { 10807 std::uint32_t len{}; 10808 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len)); 10809 } 10810 10811 case 0xDE: // map 16 10812 { 10813 std::uint16_t len{}; 10814 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len)); 10815 } 10816 10817 case 0xDF: // map 32 10818 { 10819 std::uint32_t len{}; 10820 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len)); 10821 } 10822 10823 // negative fixint 10824 case 0xE0: 10825 case 0xE1: 10826 case 0xE2: 10827 case 0xE3: 10828 case 0xE4: 10829 case 0xE5: 10830 case 0xE6: 10831 case 0xE7: 10832 case 0xE8: 10833 case 0xE9: 10834 case 0xEA: 10835 case 0xEB: 10836 case 0xEC: 10837 case 0xED: 10838 case 0xEE: 10839 case 0xEF: 10840 case 0xF0: 10841 case 0xF1: 10842 case 0xF2: 10843 case 0xF3: 10844 case 0xF4: 10845 case 0xF5: 10846 case 0xF6: 10847 case 0xF7: 10848 case 0xF8: 10849 case 0xF9: 10850 case 0xFA: 10851 case 0xFB: 10852 case 0xFC: 10853 case 0xFD: 10854 case 0xFE: 10855 case 0xFF: 10856 return sax->number_integer(static_cast<std::int8_t>(current)); 10857 10858 default: // anything else 10859 { 10860 auto last_token = get_token_string(); 10861 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 10862 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr)); 10863 } 10864 } 10865 } 10866 10867 /*! 10868 @brief reads a MessagePack string 10869 10870 This function first reads starting bytes to determine the expected 10871 string length and then copies this number of bytes into a string. 10872 10873 @param[out] result created string 10874 10875 @return whether string creation completed 10876 */ 10877 bool get_msgpack_string(string_t& result) 10878 { 10879 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) 10880 { 10881 return false; 10882 } 10883 10884 switch (current) 10885 { 10886 // fixstr 10887 case 0xA0: 10888 case 0xA1: 10889 case 0xA2: 10890 case 0xA3: 10891 case 0xA4: 10892 case 0xA5: 10893 case 0xA6: 10894 case 0xA7: 10895 case 0xA8: 10896 case 0xA9: 10897 case 0xAA: 10898 case 0xAB: 10899 case 0xAC: 10900 case 0xAD: 10901 case 0xAE: 10902 case 0xAF: 10903 case 0xB0: 10904 case 0xB1: 10905 case 0xB2: 10906 case 0xB3: 10907 case 0xB4: 10908 case 0xB5: 10909 case 0xB6: 10910 case 0xB7: 10911 case 0xB8: 10912 case 0xB9: 10913 case 0xBA: 10914 case 0xBB: 10915 case 0xBC: 10916 case 0xBD: 10917 case 0xBE: 10918 case 0xBF: 10919 { 10920 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result); 10921 } 10922 10923 case 0xD9: // str 8 10924 { 10925 std::uint8_t len{}; 10926 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); 10927 } 10928 10929 case 0xDA: // str 16 10930 { 10931 std::uint16_t len{}; 10932 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); 10933 } 10934 10935 case 0xDB: // str 32 10936 { 10937 std::uint32_t len{}; 10938 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); 10939 } 10940 10941 default: 10942 { 10943 auto last_token = get_token_string(); 10944 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, 10945 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr)); 10946 } 10947 } 10948 } 10949 10950 /*! 10951 @brief reads a MessagePack byte array 10952 10953 This function first reads starting bytes to determine the expected 10954 byte array length and then copies this number of bytes into a byte array. 10955 10956 @param[out] result created byte array 10957 10958 @return whether byte array creation completed 10959 */ 10960 bool get_msgpack_binary(binary_t& result) 10961 { 10962 // helper function to set the subtype 10963 auto assign_and_return_true = [&result](std::int8_t subtype) 10964 { 10965 result.set_subtype(static_cast<std::uint8_t>(subtype)); 10966 return true; 10967 }; 10968 10969 switch (current) 10970 { 10971 case 0xC4: // bin 8 10972 { 10973 std::uint8_t len{}; 10974 return get_number(input_format_t::msgpack, len) && 10975 get_binary(input_format_t::msgpack, len, result); 10976 } 10977 10978 case 0xC5: // bin 16 10979 { 10980 std::uint16_t len{}; 10981 return get_number(input_format_t::msgpack, len) && 10982 get_binary(input_format_t::msgpack, len, result); 10983 } 10984 10985 case 0xC6: // bin 32 10986 { 10987 std::uint32_t len{}; 10988 return get_number(input_format_t::msgpack, len) && 10989 get_binary(input_format_t::msgpack, len, result); 10990 } 10991 10992 case 0xC7: // ext 8 10993 { 10994 std::uint8_t len{}; 10995 std::int8_t subtype{}; 10996 return get_number(input_format_t::msgpack, len) && 10997 get_number(input_format_t::msgpack, subtype) && 10998 get_binary(input_format_t::msgpack, len, result) && 10999 assign_and_return_true(subtype); 11000 } 11001 11002 case 0xC8: // ext 16 11003 { 11004 std::uint16_t len{}; 11005 std::int8_t subtype{}; 11006 return get_number(input_format_t::msgpack, len) && 11007 get_number(input_format_t::msgpack, subtype) && 11008 get_binary(input_format_t::msgpack, len, result) && 11009 assign_and_return_true(subtype); 11010 } 11011 11012 case 0xC9: // ext 32 11013 { 11014 std::uint32_t len{}; 11015 std::int8_t subtype{}; 11016 return get_number(input_format_t::msgpack, len) && 11017 get_number(input_format_t::msgpack, subtype) && 11018 get_binary(input_format_t::msgpack, len, result) && 11019 assign_and_return_true(subtype); 11020 } 11021 11022 case 0xD4: // fixext 1 11023 { 11024 std::int8_t subtype{}; 11025 return get_number(input_format_t::msgpack, subtype) && 11026 get_binary(input_format_t::msgpack, 1, result) && 11027 assign_and_return_true(subtype); 11028 } 11029 11030 case 0xD5: // fixext 2 11031 { 11032 std::int8_t subtype{}; 11033 return get_number(input_format_t::msgpack, subtype) && 11034 get_binary(input_format_t::msgpack, 2, result) && 11035 assign_and_return_true(subtype); 11036 } 11037 11038 case 0xD6: // fixext 4 11039 { 11040 std::int8_t subtype{}; 11041 return get_number(input_format_t::msgpack, subtype) && 11042 get_binary(input_format_t::msgpack, 4, result) && 11043 assign_and_return_true(subtype); 11044 } 11045 11046 case 0xD7: // fixext 8 11047 { 11048 std::int8_t subtype{}; 11049 return get_number(input_format_t::msgpack, subtype) && 11050 get_binary(input_format_t::msgpack, 8, result) && 11051 assign_and_return_true(subtype); 11052 } 11053 11054 case 0xD8: // fixext 16 11055 { 11056 std::int8_t subtype{}; 11057 return get_number(input_format_t::msgpack, subtype) && 11058 get_binary(input_format_t::msgpack, 16, result) && 11059 assign_and_return_true(subtype); 11060 } 11061 11062 default: // LCOV_EXCL_LINE 11063 return false; // LCOV_EXCL_LINE 11064 } 11065 } 11066 11067 /*! 11068 @param[in] len the length of the array 11069 @return whether array creation completed 11070 */ 11071 bool get_msgpack_array(const std::size_t len) 11072 { 11073 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) 11074 { 11075 return false; 11076 } 11077 11078 for (std::size_t i = 0; i < len; ++i) 11079 { 11080 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) 11081 { 11082 return false; 11083 } 11084 } 11085 11086 return sax->end_array(); 11087 } 11088 11089 /*! 11090 @param[in] len the length of the object 11091 @return whether object creation completed 11092 */ 11093 bool get_msgpack_object(const std::size_t len) 11094 { 11095 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) 11096 { 11097 return false; 11098 } 11099 11100 string_t key; 11101 for (std::size_t i = 0; i < len; ++i) 11102 { 11103 get(); 11104 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) 11105 { 11106 return false; 11107 } 11108 11109 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) 11110 { 11111 return false; 11112 } 11113 key.clear(); 11114 } 11115 11116 return sax->end_object(); 11117 } 11118 11119 //////////// 11120 // UBJSON // 11121 //////////// 11122 11123 /*! 11124 @param[in] get_char whether a new character should be retrieved from the 11125 input (true, default) or whether the last read 11126 character should be considered instead 11127 11128 @return whether a valid UBJSON value was passed to the SAX parser 11129 */ 11130 bool parse_ubjson_internal(const bool get_char = true) 11131 { 11132 return get_ubjson_value(get_char ? get_ignore_noop() : current); 11133 } 11134 11135 /*! 11136 @brief reads a UBJSON string 11137 11138 This function is either called after reading the 'S' byte explicitly 11139 indicating a string, or in case of an object key where the 'S' byte can be 11140 left out. 11141 11142 @param[out] result created string 11143 @param[in] get_char whether a new character should be retrieved from the 11144 input (true, default) or whether the last read 11145 character should be considered instead 11146 11147 @return whether string creation completed 11148 */ 11149 bool get_ubjson_string(string_t& result, const bool get_char = true) 11150 { 11151 if (get_char) 11152 { 11153 get(); // TODO(niels): may we ignore N here? 11154 } 11155 11156 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) 11157 { 11158 return false; 11159 } 11160 11161 switch (current) 11162 { 11163 case 'U': 11164 { 11165 std::uint8_t len{}; 11166 return get_number(input_format, len) && get_string(input_format, len, result); 11167 } 11168 11169 case 'i': 11170 { 11171 std::int8_t len{}; 11172 return get_number(input_format, len) && get_string(input_format, len, result); 11173 } 11174 11175 case 'I': 11176 { 11177 std::int16_t len{}; 11178 return get_number(input_format, len) && get_string(input_format, len, result); 11179 } 11180 11181 case 'l': 11182 { 11183 std::int32_t len{}; 11184 return get_number(input_format, len) && get_string(input_format, len, result); 11185 } 11186 11187 case 'L': 11188 { 11189 std::int64_t len{}; 11190 return get_number(input_format, len) && get_string(input_format, len, result); 11191 } 11192 11193 case 'u': 11194 { 11195 if (input_format != input_format_t::bjdata) 11196 { 11197 break; 11198 } 11199 std::uint16_t len{}; 11200 return get_number(input_format, len) && get_string(input_format, len, result); 11201 } 11202 11203 case 'm': 11204 { 11205 if (input_format != input_format_t::bjdata) 11206 { 11207 break; 11208 } 11209 std::uint32_t len{}; 11210 return get_number(input_format, len) && get_string(input_format, len, result); 11211 } 11212 11213 case 'M': 11214 { 11215 if (input_format != input_format_t::bjdata) 11216 { 11217 break; 11218 } 11219 std::uint64_t len{}; 11220 return get_number(input_format, len) && get_string(input_format, len, result); 11221 } 11222 11223 default: 11224 break; 11225 } 11226 auto last_token = get_token_string(); 11227 std::string message; 11228 11229 if (input_format != input_format_t::bjdata) 11230 { 11231 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token; 11232 } 11233 else 11234 { 11235 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token; 11236 } 11237 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr)); 11238 } 11239 11240 /*! 11241 @param[out] dim an integer vector storing the ND array dimensions 11242 @return whether reading ND array size vector is successful 11243 */ 11244 bool get_ubjson_ndarray_size(std::vector<size_t>& dim) 11245 { 11246 std::pair<std::size_t, char_int_type> size_and_type; 11247 size_t dimlen = 0; 11248 bool no_ndarray = true; 11249 11250 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray))) 11251 { 11252 return false; 11253 } 11254 11255 if (size_and_type.first != npos) 11256 { 11257 if (size_and_type.second != 0) 11258 { 11259 if (size_and_type.second != 'N') 11260 { 11261 for (std::size_t i = 0; i < size_and_type.first; ++i) 11262 { 11263 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second))) 11264 { 11265 return false; 11266 } 11267 dim.push_back(dimlen); 11268 } 11269 } 11270 } 11271 else 11272 { 11273 for (std::size_t i = 0; i < size_and_type.first; ++i) 11274 { 11275 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray))) 11276 { 11277 return false; 11278 } 11279 dim.push_back(dimlen); 11280 } 11281 } 11282 } 11283 else 11284 { 11285 while (current != ']') 11286 { 11287 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current))) 11288 { 11289 return false; 11290 } 11291 dim.push_back(dimlen); 11292 get_ignore_noop(); 11293 } 11294 } 11295 return true; 11296 } 11297 11298 /*! 11299 @param[out] result determined size 11300 @param[in,out] is_ndarray for input, `true` means already inside an ndarray vector 11301 or ndarray dimension is not allowed; `false` means ndarray 11302 is allowed; for output, `true` means an ndarray is found; 11303 is_ndarray can only return `true` when its initial value 11304 is `false` 11305 @param[in] prefix type marker if already read, otherwise set to 0 11306 11307 @return whether size determination completed 11308 */ 11309 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0) 11310 { 11311 if (prefix == 0) 11312 { 11313 prefix = get_ignore_noop(); 11314 } 11315 11316 switch (prefix) 11317 { 11318 case 'U': 11319 { 11320 std::uint8_t number{}; 11321 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11322 { 11323 return false; 11324 } 11325 result = static_cast<std::size_t>(number); 11326 return true; 11327 } 11328 11329 case 'i': 11330 { 11331 std::int8_t number{}; 11332 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11333 { 11334 return false; 11335 } 11336 if (number < 0) 11337 { 11338 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, 11339 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); 11340 } 11341 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char 11342 return true; 11343 } 11344 11345 case 'I': 11346 { 11347 std::int16_t number{}; 11348 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11349 { 11350 return false; 11351 } 11352 if (number < 0) 11353 { 11354 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, 11355 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); 11356 } 11357 result = static_cast<std::size_t>(number); 11358 return true; 11359 } 11360 11361 case 'l': 11362 { 11363 std::int32_t number{}; 11364 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11365 { 11366 return false; 11367 } 11368 if (number < 0) 11369 { 11370 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, 11371 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); 11372 } 11373 result = static_cast<std::size_t>(number); 11374 return true; 11375 } 11376 11377 case 'L': 11378 { 11379 std::int64_t number{}; 11380 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11381 { 11382 return false; 11383 } 11384 if (number < 0) 11385 { 11386 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, 11387 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); 11388 } 11389 if (!value_in_range_of<std::size_t>(number)) 11390 { 11391 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, 11392 exception_message(input_format, "integer value overflow", "size"), nullptr)); 11393 } 11394 result = static_cast<std::size_t>(number); 11395 return true; 11396 } 11397 11398 case 'u': 11399 { 11400 if (input_format != input_format_t::bjdata) 11401 { 11402 break; 11403 } 11404 std::uint16_t number{}; 11405 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11406 { 11407 return false; 11408 } 11409 result = static_cast<std::size_t>(number); 11410 return true; 11411 } 11412 11413 case 'm': 11414 { 11415 if (input_format != input_format_t::bjdata) 11416 { 11417 break; 11418 } 11419 std::uint32_t number{}; 11420 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11421 { 11422 return false; 11423 } 11424 result = conditional_static_cast<std::size_t>(number); 11425 return true; 11426 } 11427 11428 case 'M': 11429 { 11430 if (input_format != input_format_t::bjdata) 11431 { 11432 break; 11433 } 11434 std::uint64_t number{}; 11435 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11436 { 11437 return false; 11438 } 11439 if (!value_in_range_of<std::size_t>(number)) 11440 { 11441 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, 11442 exception_message(input_format, "integer value overflow", "size"), nullptr)); 11443 } 11444 result = detail::conditional_static_cast<std::size_t>(number); 11445 return true; 11446 } 11447 11448 case '[': 11449 { 11450 if (input_format != input_format_t::bjdata) 11451 { 11452 break; 11453 } 11454 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array 11455 { 11456 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr)); 11457 } 11458 std::vector<size_t> dim; 11459 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim))) 11460 { 11461 return false; 11462 } 11463 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector 11464 { 11465 result = dim.at(dim.size() - 1); 11466 return true; 11467 } 11468 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format 11469 { 11470 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container 11471 { 11472 if ( i == 0 ) 11473 { 11474 result = 0; 11475 return true; 11476 } 11477 } 11478 11479 string_t key = "_ArraySize_"; 11480 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size()))) 11481 { 11482 return false; 11483 } 11484 result = 1; 11485 for (auto i : dim) 11486 { 11487 result *= i; 11488 if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type() 11489 { 11490 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr)); 11491 } 11492 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i)))) 11493 { 11494 return false; 11495 } 11496 } 11497 is_ndarray = true; 11498 return sax->end_array(); 11499 } 11500 result = 0; 11501 return true; 11502 } 11503 11504 default: 11505 break; 11506 } 11507 auto last_token = get_token_string(); 11508 std::string message; 11509 11510 if (input_format != input_format_t::bjdata) 11511 { 11512 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token; 11513 } 11514 else 11515 { 11516 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token; 11517 } 11518 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr)); 11519 } 11520 11521 /*! 11522 @brief determine the type and size for a container 11523 11524 In the optimized UBJSON format, a type and a size can be provided to allow 11525 for a more compact representation. 11526 11527 @param[out] result pair of the size and the type 11528 @param[in] inside_ndarray whether the parser is parsing an ND array dimensional vector 11529 11530 @return whether pair creation completed 11531 */ 11532 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false) 11533 { 11534 result.first = npos; // size 11535 result.second = 0; // type 11536 bool is_ndarray = false; 11537 11538 get_ignore_noop(); 11539 11540 if (current == '$') 11541 { 11542 result.second = get(); // must not ignore 'N', because 'N' maybe the type 11543 if (input_format == input_format_t::bjdata 11544 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second))) 11545 { 11546 auto last_token = get_token_string(); 11547 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 11548 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr)); 11549 } 11550 11551 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type"))) 11552 { 11553 return false; 11554 } 11555 11556 get_ignore_noop(); 11557 if (JSON_HEDLEY_UNLIKELY(current != '#')) 11558 { 11559 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) 11560 { 11561 return false; 11562 } 11563 auto last_token = get_token_string(); 11564 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 11565 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr)); 11566 } 11567 11568 const bool is_error = get_ubjson_size_value(result.first, is_ndarray); 11569 if (input_format == input_format_t::bjdata && is_ndarray) 11570 { 11571 if (inside_ndarray) 11572 { 11573 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, 11574 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr)); 11575 } 11576 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters 11577 } 11578 return is_error; 11579 } 11580 11581 if (current == '#') 11582 { 11583 const bool is_error = get_ubjson_size_value(result.first, is_ndarray); 11584 if (input_format == input_format_t::bjdata && is_ndarray) 11585 { 11586 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, 11587 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr)); 11588 } 11589 return is_error; 11590 } 11591 11592 return true; 11593 } 11594 11595 /*! 11596 @param prefix the previously read or set type prefix 11597 @return whether value creation completed 11598 */ 11599 bool get_ubjson_value(const char_int_type prefix) 11600 { 11601 switch (prefix) 11602 { 11603 case char_traits<char_type>::eof(): // EOF 11604 return unexpect_eof(input_format, "value"); 11605 11606 case 'T': // true 11607 return sax->boolean(true); 11608 case 'F': // false 11609 return sax->boolean(false); 11610 11611 case 'Z': // null 11612 return sax->null(); 11613 11614 case 'U': 11615 { 11616 std::uint8_t number{}; 11617 return get_number(input_format, number) && sax->number_unsigned(number); 11618 } 11619 11620 case 'i': 11621 { 11622 std::int8_t number{}; 11623 return get_number(input_format, number) && sax->number_integer(number); 11624 } 11625 11626 case 'I': 11627 { 11628 std::int16_t number{}; 11629 return get_number(input_format, number) && sax->number_integer(number); 11630 } 11631 11632 case 'l': 11633 { 11634 std::int32_t number{}; 11635 return get_number(input_format, number) && sax->number_integer(number); 11636 } 11637 11638 case 'L': 11639 { 11640 std::int64_t number{}; 11641 return get_number(input_format, number) && sax->number_integer(number); 11642 } 11643 11644 case 'u': 11645 { 11646 if (input_format != input_format_t::bjdata) 11647 { 11648 break; 11649 } 11650 std::uint16_t number{}; 11651 return get_number(input_format, number) && sax->number_unsigned(number); 11652 } 11653 11654 case 'm': 11655 { 11656 if (input_format != input_format_t::bjdata) 11657 { 11658 break; 11659 } 11660 std::uint32_t number{}; 11661 return get_number(input_format, number) && sax->number_unsigned(number); 11662 } 11663 11664 case 'M': 11665 { 11666 if (input_format != input_format_t::bjdata) 11667 { 11668 break; 11669 } 11670 std::uint64_t number{}; 11671 return get_number(input_format, number) && sax->number_unsigned(number); 11672 } 11673 11674 case 'h': 11675 { 11676 if (input_format != input_format_t::bjdata) 11677 { 11678 break; 11679 } 11680 const auto byte1_raw = get(); 11681 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) 11682 { 11683 return false; 11684 } 11685 const auto byte2_raw = get(); 11686 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) 11687 { 11688 return false; 11689 } 11690 11691 const auto byte1 = static_cast<unsigned char>(byte1_raw); 11692 const auto byte2 = static_cast<unsigned char>(byte2_raw); 11693 11694 // code from RFC 7049, Appendix D, Figure 3: 11695 // As half-precision floating-point numbers were only added 11696 // to IEEE 754 in 2008, today's programming platforms often 11697 // still only have limited support for them. It is very 11698 // easy to include at least decoding support for them even 11699 // without such support. An example of a small decoder for 11700 // half-precision floating-point numbers in the C language 11701 // is shown in Fig. 3. 11702 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1); 11703 const double val = [&half] 11704 { 11705 const int exp = (half >> 10u) & 0x1Fu; 11706 const unsigned int mant = half & 0x3FFu; 11707 JSON_ASSERT(0 <= exp&& exp <= 32); 11708 JSON_ASSERT(mant <= 1024); 11709 switch (exp) 11710 { 11711 case 0: 11712 return std::ldexp(mant, -24); 11713 case 31: 11714 return (mant == 0) 11715 ? std::numeric_limits<double>::infinity() 11716 : std::numeric_limits<double>::quiet_NaN(); 11717 default: 11718 return std::ldexp(mant + 1024, exp - 25); 11719 } 11720 }(); 11721 return sax->number_float((half & 0x8000u) != 0 11722 ? static_cast<number_float_t>(-val) 11723 : static_cast<number_float_t>(val), ""); 11724 } 11725 11726 case 'd': 11727 { 11728 float number{}; 11729 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), ""); 11730 } 11731 11732 case 'D': 11733 { 11734 double number{}; 11735 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), ""); 11736 } 11737 11738 case 'H': 11739 { 11740 return get_ubjson_high_precision_number(); 11741 } 11742 11743 case 'C': // char 11744 { 11745 get(); 11746 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char"))) 11747 { 11748 return false; 11749 } 11750 if (JSON_HEDLEY_UNLIKELY(current > 127)) 11751 { 11752 auto last_token = get_token_string(); 11753 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, 11754 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr)); 11755 } 11756 string_t s(1, static_cast<typename string_t::value_type>(current)); 11757 return sax->string(s); 11758 } 11759 11760 case 'S': // string 11761 { 11762 string_t s; 11763 return get_ubjson_string(s) && sax->string(s); 11764 } 11765 11766 case '[': // array 11767 return get_ubjson_array(); 11768 11769 case '{': // object 11770 return get_ubjson_object(); 11771 11772 default: // anything else 11773 break; 11774 } 11775 auto last_token = get_token_string(); 11776 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr)); 11777 } 11778 11779 /*! 11780 @return whether array creation completed 11781 */ 11782 bool get_ubjson_array() 11783 { 11784 std::pair<std::size_t, char_int_type> size_and_type; 11785 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) 11786 { 11787 return false; 11788 } 11789 11790 // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata): 11791 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]} 11792 11793 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) 11794 { 11795 size_and_type.second &= ~(static_cast<char_int_type>(1) << 8); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker 11796 auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t) 11797 { 11798 return p.first < t; 11799 }); 11800 string_t key = "_ArrayType_"; 11801 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second)) 11802 { 11803 auto last_token = get_token_string(); 11804 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 11805 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr)); 11806 } 11807 11808 string_t type = it->second; // sax->string() takes a reference 11809 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type))) 11810 { 11811 return false; 11812 } 11813 11814 if (size_and_type.second == 'C') 11815 { 11816 size_and_type.second = 'U'; 11817 } 11818 11819 key = "_ArrayData_"; 11820 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) )) 11821 { 11822 return false; 11823 } 11824 11825 for (std::size_t i = 0; i < size_and_type.first; ++i) 11826 { 11827 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) 11828 { 11829 return false; 11830 } 11831 } 11832 11833 return (sax->end_array() && sax->end_object()); 11834 } 11835 11836 if (size_and_type.first != npos) 11837 { 11838 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) 11839 { 11840 return false; 11841 } 11842 11843 if (size_and_type.second != 0) 11844 { 11845 if (size_and_type.second != 'N') 11846 { 11847 for (std::size_t i = 0; i < size_and_type.first; ++i) 11848 { 11849 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) 11850 { 11851 return false; 11852 } 11853 } 11854 } 11855 } 11856 else 11857 { 11858 for (std::size_t i = 0; i < size_and_type.first; ++i) 11859 { 11860 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) 11861 { 11862 return false; 11863 } 11864 } 11865 } 11866 } 11867 else 11868 { 11869 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) 11870 { 11871 return false; 11872 } 11873 11874 while (current != ']') 11875 { 11876 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false))) 11877 { 11878 return false; 11879 } 11880 get_ignore_noop(); 11881 } 11882 } 11883 11884 return sax->end_array(); 11885 } 11886 11887 /*! 11888 @return whether object creation completed 11889 */ 11890 bool get_ubjson_object() 11891 { 11892 std::pair<std::size_t, char_int_type> size_and_type; 11893 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) 11894 { 11895 return false; 11896 } 11897 11898 // do not accept ND-array size in objects in BJData 11899 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) 11900 { 11901 auto last_token = get_token_string(); 11902 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 11903 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr)); 11904 } 11905 11906 string_t key; 11907 if (size_and_type.first != npos) 11908 { 11909 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) 11910 { 11911 return false; 11912 } 11913 11914 if (size_and_type.second != 0) 11915 { 11916 for (std::size_t i = 0; i < size_and_type.first; ++i) 11917 { 11918 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) 11919 { 11920 return false; 11921 } 11922 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) 11923 { 11924 return false; 11925 } 11926 key.clear(); 11927 } 11928 } 11929 else 11930 { 11931 for (std::size_t i = 0; i < size_and_type.first; ++i) 11932 { 11933 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) 11934 { 11935 return false; 11936 } 11937 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) 11938 { 11939 return false; 11940 } 11941 key.clear(); 11942 } 11943 } 11944 } 11945 else 11946 { 11947 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) 11948 { 11949 return false; 11950 } 11951 11952 while (current != '}') 11953 { 11954 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) 11955 { 11956 return false; 11957 } 11958 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) 11959 { 11960 return false; 11961 } 11962 get_ignore_noop(); 11963 key.clear(); 11964 } 11965 } 11966 11967 return sax->end_object(); 11968 } 11969 11970 // Note, no reader for UBJSON binary types is implemented because they do 11971 // not exist 11972 11973 bool get_ubjson_high_precision_number() 11974 { 11975 // get size of following number string 11976 std::size_t size{}; 11977 bool no_ndarray = true; 11978 auto res = get_ubjson_size_value(size, no_ndarray); 11979 if (JSON_HEDLEY_UNLIKELY(!res)) 11980 { 11981 return res; 11982 } 11983 11984 // get number string 11985 std::vector<char> number_vector; 11986 for (std::size_t i = 0; i < size; ++i) 11987 { 11988 get(); 11989 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) 11990 { 11991 return false; 11992 } 11993 number_vector.push_back(static_cast<char>(current)); 11994 } 11995 11996 // parse number string 11997 using ia_type = decltype(detail::input_adapter(number_vector)); 11998 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false); 11999 const auto result_number = number_lexer.scan(); 12000 const auto number_string = number_lexer.get_token_string(); 12001 const auto result_remainder = number_lexer.scan(); 12002 12003 using token_type = typename detail::lexer_base<BasicJsonType>::token_type; 12004 12005 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) 12006 { 12007 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, 12008 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); 12009 } 12010 12011 switch (result_number) 12012 { 12013 case token_type::value_integer: 12014 return sax->number_integer(number_lexer.get_number_integer()); 12015 case token_type::value_unsigned: 12016 return sax->number_unsigned(number_lexer.get_number_unsigned()); 12017 case token_type::value_float: 12018 return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); 12019 case token_type::uninitialized: 12020 case token_type::literal_true: 12021 case token_type::literal_false: 12022 case token_type::literal_null: 12023 case token_type::value_string: 12024 case token_type::begin_array: 12025 case token_type::begin_object: 12026 case token_type::end_array: 12027 case token_type::end_object: 12028 case token_type::name_separator: 12029 case token_type::value_separator: 12030 case token_type::parse_error: 12031 case token_type::end_of_input: 12032 case token_type::literal_or_value: 12033 default: 12034 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, 12035 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); 12036 } 12037 } 12038 12039 /////////////////////// 12040 // Utility functions // 12041 /////////////////////// 12042 12043 /*! 12044 @brief get next character from the input 12045 12046 This function provides the interface to the used input adapter. It does 12047 not throw in case the input reached EOF, but returns a -'ve valued 12048 `char_traits<char_type>::eof()` in that case. 12049 12050 @return character read from the input 12051 */ 12052 char_int_type get() 12053 { 12054 ++chars_read; 12055 return current = ia.get_character(); 12056 } 12057 12058 /*! 12059 @brief get_to read into a primitive type 12060 12061 This function provides the interface to the used input adapter. It does 12062 not throw in case the input reached EOF, but returns false instead 12063 12064 @return bool, whether the read was successful 12065 */ 12066 template<class T> 12067 bool get_to(T& dest, const input_format_t format, const char* context) 12068 { 12069 auto new_chars_read = ia.get_elements(&dest); 12070 chars_read += new_chars_read; 12071 if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T))) 12072 { 12073 // in case of failure, advance position by 1 to report failing location 12074 ++chars_read; 12075 sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr)); 12076 return false; 12077 } 12078 return true; 12079 } 12080 12081 /*! 12082 @return character read from the input after ignoring all 'N' entries 12083 */ 12084 char_int_type get_ignore_noop() 12085 { 12086 do 12087 { 12088 get(); 12089 } 12090 while (current == 'N'); 12091 12092 return current; 12093 } 12094 12095 template<class NumberType> 12096 static void byte_swap(NumberType& number) 12097 { 12098 constexpr std::size_t sz = sizeof(number); 12099 #ifdef __cpp_lib_byteswap 12100 if constexpr (sz == 1) 12101 { 12102 return; 12103 } 12104 if constexpr(std::is_integral_v<NumberType>) 12105 { 12106 number = std::byteswap(number); 12107 return; 12108 } 12109 #endif 12110 auto* ptr = reinterpret_cast<std::uint8_t*>(&number); 12111 for (std::size_t i = 0; i < sz / 2; ++i) 12112 { 12113 std::swap(ptr[i], ptr[sz - i - 1]); 12114 } 12115 } 12116 12117 /* 12118 @brief read a number from the input 12119 12120 @tparam NumberType the type of the number 12121 @param[in] format the current format (for diagnostics) 12122 @param[out] result number of type @a NumberType 12123 12124 @return whether conversion completed 12125 12126 @note This function needs to respect the system's endianness, because 12127 bytes in CBOR, MessagePack, and UBJSON are stored in network order 12128 (big endian) and therefore need reordering on little endian systems. 12129 On the other hand, BSON and BJData use little endian and should reorder 12130 on big endian systems. 12131 */ 12132 template<typename NumberType, bool InputIsLittleEndian = false> 12133 bool get_number(const input_format_t format, NumberType& result) 12134 { 12135 // read in the original format 12136 12137 if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number"))) 12138 { 12139 return false; 12140 } 12141 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) 12142 { 12143 byte_swap(result); 12144 } 12145 return true; 12146 } 12147 12148 /*! 12149 @brief create a string by reading characters from the input 12150 12151 @tparam NumberType the type of the number 12152 @param[in] format the current format (for diagnostics) 12153 @param[in] len number of characters to read 12154 @param[out] result string created by reading @a len bytes 12155 12156 @return whether string creation completed 12157 12158 @note We can not reserve @a len bytes for the result, because @a len 12159 may be too large. Usually, @ref unexpect_eof() detects the end of 12160 the input before we run out of string memory. 12161 */ 12162 template<typename NumberType> 12163 bool get_string(const input_format_t format, 12164 const NumberType len, 12165 string_t& result) 12166 { 12167 bool success = true; 12168 for (NumberType i = 0; i < len; i++) 12169 { 12170 get(); 12171 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) 12172 { 12173 success = false; 12174 break; 12175 } 12176 result.push_back(static_cast<typename string_t::value_type>(current)); 12177 } 12178 return success; 12179 } 12180 12181 /*! 12182 @brief create a byte array by reading bytes from the input 12183 12184 @tparam NumberType the type of the number 12185 @param[in] format the current format (for diagnostics) 12186 @param[in] len number of bytes to read 12187 @param[out] result byte array created by reading @a len bytes 12188 12189 @return whether byte array creation completed 12190 12191 @note We can not reserve @a len bytes for the result, because @a len 12192 may be too large. Usually, @ref unexpect_eof() detects the end of 12193 the input before we run out of memory. 12194 */ 12195 template<typename NumberType> 12196 bool get_binary(const input_format_t format, 12197 const NumberType len, 12198 binary_t& result) 12199 { 12200 bool success = true; 12201 for (NumberType i = 0; i < len; i++) 12202 { 12203 get(); 12204 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) 12205 { 12206 success = false; 12207 break; 12208 } 12209 result.push_back(static_cast<std::uint8_t>(current)); 12210 } 12211 return success; 12212 } 12213 12214 /*! 12215 @param[in] format the current format (for diagnostics) 12216 @param[in] context further context information (for diagnostics) 12217 @return whether the last read character is not EOF 12218 */ 12219 JSON_HEDLEY_NON_NULL(3) 12220 bool unexpect_eof(const input_format_t format, const char* context) const 12221 { 12222 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof())) 12223 { 12224 return sax->parse_error(chars_read, "<end of file>", 12225 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr)); 12226 } 12227 return true; 12228 } 12229 12230 /*! 12231 @return a string representation of the last read byte 12232 */ 12233 std::string get_token_string() const 12234 { 12235 std::array<char, 3> cr{{}}; 12236 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 12237 return std::string{cr.data()}; 12238 } 12239 12240 /*! 12241 @param[in] format the current format 12242 @param[in] detail a detailed error message 12243 @param[in] context further context information 12244 @return a message string to use in the parse_error exceptions 12245 */ 12246 std::string exception_message(const input_format_t format, 12247 const std::string& detail, 12248 const std::string& context) const 12249 { 12250 std::string error_msg = "syntax error while parsing "; 12251 12252 switch (format) 12253 { 12254 case input_format_t::cbor: 12255 error_msg += "CBOR"; 12256 break; 12257 12258 case input_format_t::msgpack: 12259 error_msg += "MessagePack"; 12260 break; 12261 12262 case input_format_t::ubjson: 12263 error_msg += "UBJSON"; 12264 break; 12265 12266 case input_format_t::bson: 12267 error_msg += "BSON"; 12268 break; 12269 12270 case input_format_t::bjdata: 12271 error_msg += "BJData"; 12272 break; 12273 12274 case input_format_t::json: // LCOV_EXCL_LINE 12275 default: // LCOV_EXCL_LINE 12276 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 12277 } 12278 12279 return concat(error_msg, ' ', context, ": ", detail); 12280 } 12281 12282 private: 12283 static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1); 12284 12285 /// input adapter 12286 InputAdapterType ia; 12287 12288 /// the current character 12289 char_int_type current = char_traits<char_type>::eof(); 12290 12291 /// the number of characters read 12292 std::size_t chars_read = 0; 12293 12294 /// whether we can assume little endianness 12295 const bool is_little_endian = little_endianness(); 12296 12297 /// input format 12298 const input_format_t input_format = input_format_t::json; 12299 12300 /// the SAX parser 12301 json_sax_t* sax = nullptr; 12302 12303 // excluded markers in bjdata optimized type 12304 #define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \ 12305 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{') 12306 12307 #define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \ 12308 make_array<bjd_type>( \ 12309 bjd_type{'C', "char"}, \ 12310 bjd_type{'D', "double"}, \ 12311 bjd_type{'I', "int16"}, \ 12312 bjd_type{'L', "int64"}, \ 12313 bjd_type{'M', "uint64"}, \ 12314 bjd_type{'U', "uint8"}, \ 12315 bjd_type{'d', "single"}, \ 12316 bjd_type{'i', "int8"}, \ 12317 bjd_type{'l', "int32"}, \ 12318 bjd_type{'m', "uint32"}, \ 12319 bjd_type{'u', "uint16"}) 12320 12321 JSON_PRIVATE_UNLESS_TESTED: 12322 // lookup tables 12323 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) 12324 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers = 12325 JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_; 12326 12327 using bjd_type = std::pair<char_int_type, string_t>; 12328 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) 12329 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map = 12330 JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_; 12331 12332 #undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ 12333 #undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ 12334 }; 12335 12336 #ifndef JSON_HAS_CPP_17 12337 template<typename BasicJsonType, typename InputAdapterType, typename SAX> 12338 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos; 12339 #endif 12340 12341 } // namespace detail 12342 NLOHMANN_JSON_NAMESPACE_END 12343 12344 // #include <nlohmann/detail/input/input_adapters.hpp> 12345 12346 // #include <nlohmann/detail/input/lexer.hpp> 12347 12348 // #include <nlohmann/detail/input/parser.hpp> 12349 // __ _____ _____ _____ 12350 // __| | __| | | | JSON for Modern C++ 12351 // | | |__ | | | | | | version 3.11.3 12352 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 12353 // 12354 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 12355 // SPDX-License-Identifier: MIT 12356 12357 12358 12359 #include <cmath> // isfinite 12360 #include <cstdint> // uint8_t 12361 #include <functional> // function 12362 #include <string> // string 12363 #include <utility> // move 12364 #include <vector> // vector 12365 12366 // #include <nlohmann/detail/exceptions.hpp> 12367 12368 // #include <nlohmann/detail/input/input_adapters.hpp> 12369 12370 // #include <nlohmann/detail/input/json_sax.hpp> 12371 12372 // #include <nlohmann/detail/input/lexer.hpp> 12373 12374 // #include <nlohmann/detail/macro_scope.hpp> 12375 12376 // #include <nlohmann/detail/meta/is_sax.hpp> 12377 12378 // #include <nlohmann/detail/string_concat.hpp> 12379 12380 // #include <nlohmann/detail/value_t.hpp> 12381 12382 12383 NLOHMANN_JSON_NAMESPACE_BEGIN 12384 namespace detail 12385 { 12386 //////////// 12387 // parser // 12388 //////////// 12389 12390 enum class parse_event_t : std::uint8_t 12391 { 12392 /// the parser read `{` and started to process a JSON object 12393 object_start, 12394 /// the parser read `}` and finished processing a JSON object 12395 object_end, 12396 /// the parser read `[` and started to process a JSON array 12397 array_start, 12398 /// the parser read `]` and finished processing a JSON array 12399 array_end, 12400 /// the parser read a key of a value in an object 12401 key, 12402 /// the parser finished reading a JSON value 12403 value 12404 }; 12405 12406 template<typename BasicJsonType> 12407 using parser_callback_t = 12408 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>; 12409 12410 /*! 12411 @brief syntax analysis 12412 12413 This class implements a recursive descent parser. 12414 */ 12415 template<typename BasicJsonType, typename InputAdapterType> 12416 class parser 12417 { 12418 using number_integer_t = typename BasicJsonType::number_integer_t; 12419 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 12420 using number_float_t = typename BasicJsonType::number_float_t; 12421 using string_t = typename BasicJsonType::string_t; 12422 using lexer_t = lexer<BasicJsonType, InputAdapterType>; 12423 using token_type = typename lexer_t::token_type; 12424 12425 public: 12426 /// a parser reading from an input adapter 12427 explicit parser(InputAdapterType&& adapter, 12428 parser_callback_t<BasicJsonType> cb = nullptr, 12429 const bool allow_exceptions_ = true, 12430 const bool skip_comments = false) 12431 : callback(std::move(cb)) 12432 , m_lexer(std::move(adapter), skip_comments) 12433 , allow_exceptions(allow_exceptions_) 12434 { 12435 // read first token 12436 get_token(); 12437 } 12438 12439 /*! 12440 @brief public parser interface 12441 12442 @param[in] strict whether to expect the last token to be EOF 12443 @param[in,out] result parsed JSON value 12444 12445 @throw parse_error.101 in case of an unexpected token 12446 @throw parse_error.102 if to_unicode fails or surrogate error 12447 @throw parse_error.103 if to_unicode fails 12448 */ 12449 void parse(const bool strict, BasicJsonType& result) 12450 { 12451 if (callback) 12452 { 12453 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions); 12454 sax_parse_internal(&sdp); 12455 12456 // in strict mode, input must be completely read 12457 if (strict && (get_token() != token_type::end_of_input)) 12458 { 12459 sdp.parse_error(m_lexer.get_position(), 12460 m_lexer.get_token_string(), 12461 parse_error::create(101, m_lexer.get_position(), 12462 exception_message(token_type::end_of_input, "value"), nullptr)); 12463 } 12464 12465 // in case of an error, return discarded value 12466 if (sdp.is_errored()) 12467 { 12468 result = value_t::discarded; 12469 return; 12470 } 12471 12472 // set top-level value to null if it was discarded by the callback 12473 // function 12474 if (result.is_discarded()) 12475 { 12476 result = nullptr; 12477 } 12478 } 12479 else 12480 { 12481 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions); 12482 sax_parse_internal(&sdp); 12483 12484 // in strict mode, input must be completely read 12485 if (strict && (get_token() != token_type::end_of_input)) 12486 { 12487 sdp.parse_error(m_lexer.get_position(), 12488 m_lexer.get_token_string(), 12489 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); 12490 } 12491 12492 // in case of an error, return discarded value 12493 if (sdp.is_errored()) 12494 { 12495 result = value_t::discarded; 12496 return; 12497 } 12498 } 12499 12500 result.assert_invariant(); 12501 } 12502 12503 /*! 12504 @brief public accept interface 12505 12506 @param[in] strict whether to expect the last token to be EOF 12507 @return whether the input is a proper JSON text 12508 */ 12509 bool accept(const bool strict = true) 12510 { 12511 json_sax_acceptor<BasicJsonType> sax_acceptor; 12512 return sax_parse(&sax_acceptor, strict); 12513 } 12514 12515 template<typename SAX> 12516 JSON_HEDLEY_NON_NULL(2) 12517 bool sax_parse(SAX* sax, const bool strict = true) 12518 { 12519 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {}; 12520 const bool result = sax_parse_internal(sax); 12521 12522 // strict mode: next byte must be EOF 12523 if (result && strict && (get_token() != token_type::end_of_input)) 12524 { 12525 return sax->parse_error(m_lexer.get_position(), 12526 m_lexer.get_token_string(), 12527 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); 12528 } 12529 12530 return result; 12531 } 12532 12533 private: 12534 template<typename SAX> 12535 JSON_HEDLEY_NON_NULL(2) 12536 bool sax_parse_internal(SAX* sax) 12537 { 12538 // stack to remember the hierarchy of structured values we are parsing 12539 // true = array; false = object 12540 std::vector<bool> states; 12541 // value to avoid a goto (see comment where set to true) 12542 bool skip_to_state_evaluation = false; 12543 12544 while (true) 12545 { 12546 if (!skip_to_state_evaluation) 12547 { 12548 // invariant: get_token() was called before each iteration 12549 switch (last_token) 12550 { 12551 case token_type::begin_object: 12552 { 12553 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) 12554 { 12555 return false; 12556 } 12557 12558 // closing } -> we are done 12559 if (get_token() == token_type::end_object) 12560 { 12561 if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) 12562 { 12563 return false; 12564 } 12565 break; 12566 } 12567 12568 // parse key 12569 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) 12570 { 12571 return sax->parse_error(m_lexer.get_position(), 12572 m_lexer.get_token_string(), 12573 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); 12574 } 12575 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) 12576 { 12577 return false; 12578 } 12579 12580 // parse separator (:) 12581 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) 12582 { 12583 return sax->parse_error(m_lexer.get_position(), 12584 m_lexer.get_token_string(), 12585 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); 12586 } 12587 12588 // remember we are now inside an object 12589 states.push_back(false); 12590 12591 // parse values 12592 get_token(); 12593 continue; 12594 } 12595 12596 case token_type::begin_array: 12597 { 12598 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) 12599 { 12600 return false; 12601 } 12602 12603 // closing ] -> we are done 12604 if (get_token() == token_type::end_array) 12605 { 12606 if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) 12607 { 12608 return false; 12609 } 12610 break; 12611 } 12612 12613 // remember we are now inside an array 12614 states.push_back(true); 12615 12616 // parse values (no need to call get_token) 12617 continue; 12618 } 12619 12620 case token_type::value_float: 12621 { 12622 const auto res = m_lexer.get_number_float(); 12623 12624 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) 12625 { 12626 return sax->parse_error(m_lexer.get_position(), 12627 m_lexer.get_token_string(), 12628 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr)); 12629 } 12630 12631 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) 12632 { 12633 return false; 12634 } 12635 12636 break; 12637 } 12638 12639 case token_type::literal_false: 12640 { 12641 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) 12642 { 12643 return false; 12644 } 12645 break; 12646 } 12647 12648 case token_type::literal_null: 12649 { 12650 if (JSON_HEDLEY_UNLIKELY(!sax->null())) 12651 { 12652 return false; 12653 } 12654 break; 12655 } 12656 12657 case token_type::literal_true: 12658 { 12659 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) 12660 { 12661 return false; 12662 } 12663 break; 12664 } 12665 12666 case token_type::value_integer: 12667 { 12668 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) 12669 { 12670 return false; 12671 } 12672 break; 12673 } 12674 12675 case token_type::value_string: 12676 { 12677 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) 12678 { 12679 return false; 12680 } 12681 break; 12682 } 12683 12684 case token_type::value_unsigned: 12685 { 12686 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) 12687 { 12688 return false; 12689 } 12690 break; 12691 } 12692 12693 case token_type::parse_error: 12694 { 12695 // using "uninitialized" to avoid "expected" message 12696 return sax->parse_error(m_lexer.get_position(), 12697 m_lexer.get_token_string(), 12698 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr)); 12699 } 12700 case token_type::end_of_input: 12701 { 12702 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1)) 12703 { 12704 return sax->parse_error(m_lexer.get_position(), 12705 m_lexer.get_token_string(), 12706 parse_error::create(101, m_lexer.get_position(), 12707 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr)); 12708 } 12709 12710 return sax->parse_error(m_lexer.get_position(), 12711 m_lexer.get_token_string(), 12712 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); 12713 } 12714 case token_type::uninitialized: 12715 case token_type::end_array: 12716 case token_type::end_object: 12717 case token_type::name_separator: 12718 case token_type::value_separator: 12719 case token_type::literal_or_value: 12720 default: // the last token was unexpected 12721 { 12722 return sax->parse_error(m_lexer.get_position(), 12723 m_lexer.get_token_string(), 12724 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); 12725 } 12726 } 12727 } 12728 else 12729 { 12730 skip_to_state_evaluation = false; 12731 } 12732 12733 // we reached this line after we successfully parsed a value 12734 if (states.empty()) 12735 { 12736 // empty stack: we reached the end of the hierarchy: done 12737 return true; 12738 } 12739 12740 if (states.back()) // array 12741 { 12742 // comma -> next value 12743 if (get_token() == token_type::value_separator) 12744 { 12745 // parse a new value 12746 get_token(); 12747 continue; 12748 } 12749 12750 // closing ] 12751 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) 12752 { 12753 if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) 12754 { 12755 return false; 12756 } 12757 12758 // We are done with this array. Before we can parse a 12759 // new value, we need to evaluate the new state first. 12760 // By setting skip_to_state_evaluation to false, we 12761 // are effectively jumping to the beginning of this if. 12762 JSON_ASSERT(!states.empty()); 12763 states.pop_back(); 12764 skip_to_state_evaluation = true; 12765 continue; 12766 } 12767 12768 return sax->parse_error(m_lexer.get_position(), 12769 m_lexer.get_token_string(), 12770 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr)); 12771 } 12772 12773 // states.back() is false -> object 12774 12775 // comma -> next value 12776 if (get_token() == token_type::value_separator) 12777 { 12778 // parse key 12779 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) 12780 { 12781 return sax->parse_error(m_lexer.get_position(), 12782 m_lexer.get_token_string(), 12783 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); 12784 } 12785 12786 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) 12787 { 12788 return false; 12789 } 12790 12791 // parse separator (:) 12792 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) 12793 { 12794 return sax->parse_error(m_lexer.get_position(), 12795 m_lexer.get_token_string(), 12796 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); 12797 } 12798 12799 // parse values 12800 get_token(); 12801 continue; 12802 } 12803 12804 // closing } 12805 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) 12806 { 12807 if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) 12808 { 12809 return false; 12810 } 12811 12812 // We are done with this object. Before we can parse a 12813 // new value, we need to evaluate the new state first. 12814 // By setting skip_to_state_evaluation to false, we 12815 // are effectively jumping to the beginning of this if. 12816 JSON_ASSERT(!states.empty()); 12817 states.pop_back(); 12818 skip_to_state_evaluation = true; 12819 continue; 12820 } 12821 12822 return sax->parse_error(m_lexer.get_position(), 12823 m_lexer.get_token_string(), 12824 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr)); 12825 } 12826 } 12827 12828 /// get next token from lexer 12829 token_type get_token() 12830 { 12831 return last_token = m_lexer.scan(); 12832 } 12833 12834 std::string exception_message(const token_type expected, const std::string& context) 12835 { 12836 std::string error_msg = "syntax error "; 12837 12838 if (!context.empty()) 12839 { 12840 error_msg += concat("while parsing ", context, ' '); 12841 } 12842 12843 error_msg += "- "; 12844 12845 if (last_token == token_type::parse_error) 12846 { 12847 error_msg += concat(m_lexer.get_error_message(), "; last read: '", 12848 m_lexer.get_token_string(), '\''); 12849 } 12850 else 12851 { 12852 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token)); 12853 } 12854 12855 if (expected != token_type::uninitialized) 12856 { 12857 error_msg += concat("; expected ", lexer_t::token_type_name(expected)); 12858 } 12859 12860 return error_msg; 12861 } 12862 12863 private: 12864 /// callback function 12865 const parser_callback_t<BasicJsonType> callback = nullptr; 12866 /// the type of the last read token 12867 token_type last_token = token_type::uninitialized; 12868 /// the lexer 12869 lexer_t m_lexer; 12870 /// whether to throw exceptions in case of errors 12871 const bool allow_exceptions = true; 12872 }; 12873 12874 } // namespace detail 12875 NLOHMANN_JSON_NAMESPACE_END 12876 12877 // #include <nlohmann/detail/iterators/internal_iterator.hpp> 12878 // __ _____ _____ _____ 12879 // __| | __| | | | JSON for Modern C++ 12880 // | | |__ | | | | | | version 3.11.3 12881 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 12882 // 12883 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 12884 // SPDX-License-Identifier: MIT 12885 12886 12887 12888 // #include <nlohmann/detail/abi_macros.hpp> 12889 12890 // #include <nlohmann/detail/iterators/primitive_iterator.hpp> 12891 // __ _____ _____ _____ 12892 // __| | __| | | | JSON for Modern C++ 12893 // | | |__ | | | | | | version 3.11.3 12894 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 12895 // 12896 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 12897 // SPDX-License-Identifier: MIT 12898 12899 12900 12901 #include <cstddef> // ptrdiff_t 12902 #include <limits> // numeric_limits 12903 12904 // #include <nlohmann/detail/macro_scope.hpp> 12905 12906 12907 NLOHMANN_JSON_NAMESPACE_BEGIN 12908 namespace detail 12909 { 12910 12911 /* 12912 @brief an iterator for primitive JSON types 12913 12914 This class models an iterator for primitive JSON types (boolean, number, 12915 string). It's only purpose is to allow the iterator/const_iterator classes 12916 to "iterate" over primitive values. Internally, the iterator is modeled by 12917 a `difference_type` variable. Value begin_value (`0`) models the begin, 12918 end_value (`1`) models past the end. 12919 */ 12920 class primitive_iterator_t 12921 { 12922 private: 12923 using difference_type = std::ptrdiff_t; 12924 static constexpr difference_type begin_value = 0; 12925 static constexpr difference_type end_value = begin_value + 1; 12926 12927 JSON_PRIVATE_UNLESS_TESTED: 12928 /// iterator as signed integer type 12929 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)(); 12930 12931 public: 12932 constexpr difference_type get_value() const noexcept 12933 { 12934 return m_it; 12935 } 12936 12937 /// set iterator to a defined beginning 12938 void set_begin() noexcept 12939 { 12940 m_it = begin_value; 12941 } 12942 12943 /// set iterator to a defined past the end 12944 void set_end() noexcept 12945 { 12946 m_it = end_value; 12947 } 12948 12949 /// return whether the iterator can be dereferenced 12950 constexpr bool is_begin() const noexcept 12951 { 12952 return m_it == begin_value; 12953 } 12954 12955 /// return whether the iterator is at end 12956 constexpr bool is_end() const noexcept 12957 { 12958 return m_it == end_value; 12959 } 12960 12961 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept 12962 { 12963 return lhs.m_it == rhs.m_it; 12964 } 12965 12966 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept 12967 { 12968 return lhs.m_it < rhs.m_it; 12969 } 12970 12971 primitive_iterator_t operator+(difference_type n) noexcept 12972 { 12973 auto result = *this; 12974 result += n; 12975 return result; 12976 } 12977 12978 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept 12979 { 12980 return lhs.m_it - rhs.m_it; 12981 } 12982 12983 primitive_iterator_t& operator++() noexcept 12984 { 12985 ++m_it; 12986 return *this; 12987 } 12988 12989 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp) 12990 { 12991 auto result = *this; 12992 ++m_it; 12993 return result; 12994 } 12995 12996 primitive_iterator_t& operator--() noexcept 12997 { 12998 --m_it; 12999 return *this; 13000 } 13001 13002 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp) 13003 { 13004 auto result = *this; 13005 --m_it; 13006 return result; 13007 } 13008 13009 primitive_iterator_t& operator+=(difference_type n) noexcept 13010 { 13011 m_it += n; 13012 return *this; 13013 } 13014 13015 primitive_iterator_t& operator-=(difference_type n) noexcept 13016 { 13017 m_it -= n; 13018 return *this; 13019 } 13020 }; 13021 13022 } // namespace detail 13023 NLOHMANN_JSON_NAMESPACE_END 13024 13025 13026 NLOHMANN_JSON_NAMESPACE_BEGIN 13027 namespace detail 13028 { 13029 13030 /*! 13031 @brief an iterator value 13032 13033 @note This structure could easily be a union, but MSVC currently does not allow 13034 unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. 13035 */ 13036 template<typename BasicJsonType> struct internal_iterator 13037 { 13038 /// iterator for JSON objects 13039 typename BasicJsonType::object_t::iterator object_iterator {}; 13040 /// iterator for JSON arrays 13041 typename BasicJsonType::array_t::iterator array_iterator {}; 13042 /// generic iterator for all other types 13043 primitive_iterator_t primitive_iterator {}; 13044 }; 13045 13046 } // namespace detail 13047 NLOHMANN_JSON_NAMESPACE_END 13048 13049 // #include <nlohmann/detail/iterators/iter_impl.hpp> 13050 // __ _____ _____ _____ 13051 // __| | __| | | | JSON for Modern C++ 13052 // | | |__ | | | | | | version 3.11.3 13053 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 13054 // 13055 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 13056 // SPDX-License-Identifier: MIT 13057 13058 13059 13060 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next 13061 #include <type_traits> // conditional, is_const, remove_const 13062 13063 // #include <nlohmann/detail/exceptions.hpp> 13064 13065 // #include <nlohmann/detail/iterators/internal_iterator.hpp> 13066 13067 // #include <nlohmann/detail/iterators/primitive_iterator.hpp> 13068 13069 // #include <nlohmann/detail/macro_scope.hpp> 13070 13071 // #include <nlohmann/detail/meta/cpp_future.hpp> 13072 13073 // #include <nlohmann/detail/meta/type_traits.hpp> 13074 13075 // #include <nlohmann/detail/value_t.hpp> 13076 13077 13078 NLOHMANN_JSON_NAMESPACE_BEGIN 13079 namespace detail 13080 { 13081 13082 // forward declare, to be able to friend it later on 13083 template<typename IteratorType> class iteration_proxy; 13084 template<typename IteratorType> class iteration_proxy_value; 13085 13086 /*! 13087 @brief a template for a bidirectional iterator for the @ref basic_json class 13088 This class implements a both iterators (iterator and const_iterator) for the 13089 @ref basic_json class. 13090 @note An iterator is called *initialized* when a pointer to a JSON value has 13091 been set (e.g., by a constructor or a copy assignment). If the iterator is 13092 default-constructed, it is *uninitialized* and most methods are undefined. 13093 **The library uses assertions to detect calls on uninitialized iterators.** 13094 @requirement The class satisfies the following concept requirements: 13095 - 13096 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): 13097 The iterator that can be moved can be moved in both directions (i.e. 13098 incremented and decremented). 13099 @since version 1.0.0, simplified in version 2.0.9, change to bidirectional 13100 iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) 13101 */ 13102 template<typename BasicJsonType> 13103 class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) 13104 { 13105 /// the iterator with BasicJsonType of different const-ness 13106 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>; 13107 /// allow basic_json to access private members 13108 friend other_iter_impl; 13109 friend BasicJsonType; 13110 friend iteration_proxy<iter_impl>; 13111 friend iteration_proxy_value<iter_impl>; 13112 13113 using object_t = typename BasicJsonType::object_t; 13114 using array_t = typename BasicJsonType::array_t; 13115 // make sure BasicJsonType is basic_json or const basic_json 13116 static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value, 13117 "iter_impl only accepts (const) basic_json"); 13118 // superficial check for the LegacyBidirectionalIterator named requirement 13119 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value 13120 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value, 13121 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement."); 13122 13123 public: 13124 /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. 13125 /// The C++ Standard has never required user-defined iterators to derive from std::iterator. 13126 /// A user-defined iterator should provide publicly accessible typedefs named 13127 /// iterator_category, value_type, difference_type, pointer, and reference. 13128 /// Note that value_type is required to be non-const, even for constant iterators. 13129 using iterator_category = std::bidirectional_iterator_tag; 13130 13131 /// the type of the values when the iterator is dereferenced 13132 using value_type = typename BasicJsonType::value_type; 13133 /// a type to represent differences between iterators 13134 using difference_type = typename BasicJsonType::difference_type; 13135 /// defines a pointer to the type iterated over (value_type) 13136 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value, 13137 typename BasicJsonType::const_pointer, 13138 typename BasicJsonType::pointer>::type; 13139 /// defines a reference to the type iterated over (value_type) 13140 using reference = 13141 typename std::conditional<std::is_const<BasicJsonType>::value, 13142 typename BasicJsonType::const_reference, 13143 typename BasicJsonType::reference>::type; 13144 13145 iter_impl() = default; 13146 ~iter_impl() = default; 13147 iter_impl(iter_impl&&) noexcept = default; 13148 iter_impl& operator=(iter_impl&&) noexcept = default; 13149 13150 /*! 13151 @brief constructor for a given JSON instance 13152 @param[in] object pointer to a JSON object for this iterator 13153 @pre object != nullptr 13154 @post The iterator is initialized; i.e. `m_object != nullptr`. 13155 */ 13156 explicit iter_impl(pointer object) noexcept : m_object(object) 13157 { 13158 JSON_ASSERT(m_object != nullptr); 13159 13160 switch (m_object->m_data.m_type) 13161 { 13162 case value_t::object: 13163 { 13164 m_it.object_iterator = typename object_t::iterator(); 13165 break; 13166 } 13167 13168 case value_t::array: 13169 { 13170 m_it.array_iterator = typename array_t::iterator(); 13171 break; 13172 } 13173 13174 case value_t::null: 13175 case value_t::string: 13176 case value_t::boolean: 13177 case value_t::number_integer: 13178 case value_t::number_unsigned: 13179 case value_t::number_float: 13180 case value_t::binary: 13181 case value_t::discarded: 13182 default: 13183 { 13184 m_it.primitive_iterator = primitive_iterator_t(); 13185 break; 13186 } 13187 } 13188 } 13189 13190 /*! 13191 @note The conventional copy constructor and copy assignment are implicitly 13192 defined. Combined with the following converting constructor and 13193 assignment, they support: (1) copy from iterator to iterator, (2) 13194 copy from const iterator to const iterator, and (3) conversion from 13195 iterator to const iterator. However conversion from const iterator 13196 to iterator is not defined. 13197 */ 13198 13199 /*! 13200 @brief const copy constructor 13201 @param[in] other const iterator to copy from 13202 @note This copy constructor had to be defined explicitly to circumvent a bug 13203 occurring on msvc v19.0 compiler (VS 2015) debug build. For more 13204 information refer to: https://github.com/nlohmann/json/issues/1608 13205 */ 13206 iter_impl(const iter_impl<const BasicJsonType>& other) noexcept 13207 : m_object(other.m_object), m_it(other.m_it) 13208 {} 13209 13210 /*! 13211 @brief converting assignment 13212 @param[in] other const iterator to copy from 13213 @return const/non-const iterator 13214 @note It is not checked whether @a other is initialized. 13215 */ 13216 iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept 13217 { 13218 if (&other != this) 13219 { 13220 m_object = other.m_object; 13221 m_it = other.m_it; 13222 } 13223 return *this; 13224 } 13225 13226 /*! 13227 @brief converting constructor 13228 @param[in] other non-const iterator to copy from 13229 @note It is not checked whether @a other is initialized. 13230 */ 13231 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept 13232 : m_object(other.m_object), m_it(other.m_it) 13233 {} 13234 13235 /*! 13236 @brief converting assignment 13237 @param[in] other non-const iterator to copy from 13238 @return const/non-const iterator 13239 @note It is not checked whether @a other is initialized. 13240 */ 13241 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp) 13242 { 13243 m_object = other.m_object; 13244 m_it = other.m_it; 13245 return *this; 13246 } 13247 13248 JSON_PRIVATE_UNLESS_TESTED: 13249 /*! 13250 @brief set the iterator to the first value 13251 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13252 */ 13253 void set_begin() noexcept 13254 { 13255 JSON_ASSERT(m_object != nullptr); 13256 13257 switch (m_object->m_data.m_type) 13258 { 13259 case value_t::object: 13260 { 13261 m_it.object_iterator = m_object->m_data.m_value.object->begin(); 13262 break; 13263 } 13264 13265 case value_t::array: 13266 { 13267 m_it.array_iterator = m_object->m_data.m_value.array->begin(); 13268 break; 13269 } 13270 13271 case value_t::null: 13272 { 13273 // set to end so begin()==end() is true: null is empty 13274 m_it.primitive_iterator.set_end(); 13275 break; 13276 } 13277 13278 case value_t::string: 13279 case value_t::boolean: 13280 case value_t::number_integer: 13281 case value_t::number_unsigned: 13282 case value_t::number_float: 13283 case value_t::binary: 13284 case value_t::discarded: 13285 default: 13286 { 13287 m_it.primitive_iterator.set_begin(); 13288 break; 13289 } 13290 } 13291 } 13292 13293 /*! 13294 @brief set the iterator past the last value 13295 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13296 */ 13297 void set_end() noexcept 13298 { 13299 JSON_ASSERT(m_object != nullptr); 13300 13301 switch (m_object->m_data.m_type) 13302 { 13303 case value_t::object: 13304 { 13305 m_it.object_iterator = m_object->m_data.m_value.object->end(); 13306 break; 13307 } 13308 13309 case value_t::array: 13310 { 13311 m_it.array_iterator = m_object->m_data.m_value.array->end(); 13312 break; 13313 } 13314 13315 case value_t::null: 13316 case value_t::string: 13317 case value_t::boolean: 13318 case value_t::number_integer: 13319 case value_t::number_unsigned: 13320 case value_t::number_float: 13321 case value_t::binary: 13322 case value_t::discarded: 13323 default: 13324 { 13325 m_it.primitive_iterator.set_end(); 13326 break; 13327 } 13328 } 13329 } 13330 13331 public: 13332 /*! 13333 @brief return a reference to the value pointed to by the iterator 13334 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13335 */ 13336 reference operator*() const 13337 { 13338 JSON_ASSERT(m_object != nullptr); 13339 13340 switch (m_object->m_data.m_type) 13341 { 13342 case value_t::object: 13343 { 13344 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); 13345 return m_it.object_iterator->second; 13346 } 13347 13348 case value_t::array: 13349 { 13350 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); 13351 return *m_it.array_iterator; 13352 } 13353 13354 case value_t::null: 13355 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); 13356 13357 case value_t::string: 13358 case value_t::boolean: 13359 case value_t::number_integer: 13360 case value_t::number_unsigned: 13361 case value_t::number_float: 13362 case value_t::binary: 13363 case value_t::discarded: 13364 default: 13365 { 13366 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) 13367 { 13368 return *m_object; 13369 } 13370 13371 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); 13372 } 13373 } 13374 } 13375 13376 /*! 13377 @brief dereference the iterator 13378 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13379 */ 13380 pointer operator->() const 13381 { 13382 JSON_ASSERT(m_object != nullptr); 13383 13384 switch (m_object->m_data.m_type) 13385 { 13386 case value_t::object: 13387 { 13388 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); 13389 return &(m_it.object_iterator->second); 13390 } 13391 13392 case value_t::array: 13393 { 13394 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); 13395 return &*m_it.array_iterator; 13396 } 13397 13398 case value_t::null: 13399 case value_t::string: 13400 case value_t::boolean: 13401 case value_t::number_integer: 13402 case value_t::number_unsigned: 13403 case value_t::number_float: 13404 case value_t::binary: 13405 case value_t::discarded: 13406 default: 13407 { 13408 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) 13409 { 13410 return m_object; 13411 } 13412 13413 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); 13414 } 13415 } 13416 } 13417 13418 /*! 13419 @brief post-increment (it++) 13420 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13421 */ 13422 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp) 13423 { 13424 auto result = *this; 13425 ++(*this); 13426 return result; 13427 } 13428 13429 /*! 13430 @brief pre-increment (++it) 13431 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13432 */ 13433 iter_impl& operator++() 13434 { 13435 JSON_ASSERT(m_object != nullptr); 13436 13437 switch (m_object->m_data.m_type) 13438 { 13439 case value_t::object: 13440 { 13441 std::advance(m_it.object_iterator, 1); 13442 break; 13443 } 13444 13445 case value_t::array: 13446 { 13447 std::advance(m_it.array_iterator, 1); 13448 break; 13449 } 13450 13451 case value_t::null: 13452 case value_t::string: 13453 case value_t::boolean: 13454 case value_t::number_integer: 13455 case value_t::number_unsigned: 13456 case value_t::number_float: 13457 case value_t::binary: 13458 case value_t::discarded: 13459 default: 13460 { 13461 ++m_it.primitive_iterator; 13462 break; 13463 } 13464 } 13465 13466 return *this; 13467 } 13468 13469 /*! 13470 @brief post-decrement (it--) 13471 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13472 */ 13473 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp) 13474 { 13475 auto result = *this; 13476 --(*this); 13477 return result; 13478 } 13479 13480 /*! 13481 @brief pre-decrement (--it) 13482 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13483 */ 13484 iter_impl& operator--() 13485 { 13486 JSON_ASSERT(m_object != nullptr); 13487 13488 switch (m_object->m_data.m_type) 13489 { 13490 case value_t::object: 13491 { 13492 std::advance(m_it.object_iterator, -1); 13493 break; 13494 } 13495 13496 case value_t::array: 13497 { 13498 std::advance(m_it.array_iterator, -1); 13499 break; 13500 } 13501 13502 case value_t::null: 13503 case value_t::string: 13504 case value_t::boolean: 13505 case value_t::number_integer: 13506 case value_t::number_unsigned: 13507 case value_t::number_float: 13508 case value_t::binary: 13509 case value_t::discarded: 13510 default: 13511 { 13512 --m_it.primitive_iterator; 13513 break; 13514 } 13515 } 13516 13517 return *this; 13518 } 13519 13520 /*! 13521 @brief comparison: equal 13522 @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. 13523 */ 13524 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr > 13525 bool operator==(const IterImpl& other) const 13526 { 13527 // if objects are not the same, the comparison is undefined 13528 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) 13529 { 13530 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); 13531 } 13532 13533 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493 13534 if (m_object == nullptr) 13535 { 13536 return true; 13537 } 13538 13539 switch (m_object->m_data.m_type) 13540 { 13541 case value_t::object: 13542 return (m_it.object_iterator == other.m_it.object_iterator); 13543 13544 case value_t::array: 13545 return (m_it.array_iterator == other.m_it.array_iterator); 13546 13547 case value_t::null: 13548 case value_t::string: 13549 case value_t::boolean: 13550 case value_t::number_integer: 13551 case value_t::number_unsigned: 13552 case value_t::number_float: 13553 case value_t::binary: 13554 case value_t::discarded: 13555 default: 13556 return (m_it.primitive_iterator == other.m_it.primitive_iterator); 13557 } 13558 } 13559 13560 /*! 13561 @brief comparison: not equal 13562 @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. 13563 */ 13564 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr > 13565 bool operator!=(const IterImpl& other) const 13566 { 13567 return !operator==(other); 13568 } 13569 13570 /*! 13571 @brief comparison: smaller 13572 @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. 13573 */ 13574 bool operator<(const iter_impl& other) const 13575 { 13576 // if objects are not the same, the comparison is undefined 13577 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) 13578 { 13579 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); 13580 } 13581 13582 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493 13583 if (m_object == nullptr) 13584 { 13585 // the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false 13586 return false; 13587 } 13588 13589 switch (m_object->m_data.m_type) 13590 { 13591 case value_t::object: 13592 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object)); 13593 13594 case value_t::array: 13595 return (m_it.array_iterator < other.m_it.array_iterator); 13596 13597 case value_t::null: 13598 case value_t::string: 13599 case value_t::boolean: 13600 case value_t::number_integer: 13601 case value_t::number_unsigned: 13602 case value_t::number_float: 13603 case value_t::binary: 13604 case value_t::discarded: 13605 default: 13606 return (m_it.primitive_iterator < other.m_it.primitive_iterator); 13607 } 13608 } 13609 13610 /*! 13611 @brief comparison: less than or equal 13612 @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. 13613 */ 13614 bool operator<=(const iter_impl& other) const 13615 { 13616 return !other.operator < (*this); 13617 } 13618 13619 /*! 13620 @brief comparison: greater than 13621 @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. 13622 */ 13623 bool operator>(const iter_impl& other) const 13624 { 13625 return !operator<=(other); 13626 } 13627 13628 /*! 13629 @brief comparison: greater than or equal 13630 @pre (1) The iterator is initialized; i.e. `m_object != nullptr`, or (2) both iterators are value-initialized. 13631 */ 13632 bool operator>=(const iter_impl& other) const 13633 { 13634 return !operator<(other); 13635 } 13636 13637 /*! 13638 @brief add to iterator 13639 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13640 */ 13641 iter_impl& operator+=(difference_type i) 13642 { 13643 JSON_ASSERT(m_object != nullptr); 13644 13645 switch (m_object->m_data.m_type) 13646 { 13647 case value_t::object: 13648 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); 13649 13650 case value_t::array: 13651 { 13652 std::advance(m_it.array_iterator, i); 13653 break; 13654 } 13655 13656 case value_t::null: 13657 case value_t::string: 13658 case value_t::boolean: 13659 case value_t::number_integer: 13660 case value_t::number_unsigned: 13661 case value_t::number_float: 13662 case value_t::binary: 13663 case value_t::discarded: 13664 default: 13665 { 13666 m_it.primitive_iterator += i; 13667 break; 13668 } 13669 } 13670 13671 return *this; 13672 } 13673 13674 /*! 13675 @brief subtract from iterator 13676 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13677 */ 13678 iter_impl& operator-=(difference_type i) 13679 { 13680 return operator+=(-i); 13681 } 13682 13683 /*! 13684 @brief add to iterator 13685 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13686 */ 13687 iter_impl operator+(difference_type i) const 13688 { 13689 auto result = *this; 13690 result += i; 13691 return result; 13692 } 13693 13694 /*! 13695 @brief addition of distance and iterator 13696 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13697 */ 13698 friend iter_impl operator+(difference_type i, const iter_impl& it) 13699 { 13700 auto result = it; 13701 result += i; 13702 return result; 13703 } 13704 13705 /*! 13706 @brief subtract from iterator 13707 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13708 */ 13709 iter_impl operator-(difference_type i) const 13710 { 13711 auto result = *this; 13712 result -= i; 13713 return result; 13714 } 13715 13716 /*! 13717 @brief return difference 13718 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13719 */ 13720 difference_type operator-(const iter_impl& other) const 13721 { 13722 JSON_ASSERT(m_object != nullptr); 13723 13724 switch (m_object->m_data.m_type) 13725 { 13726 case value_t::object: 13727 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); 13728 13729 case value_t::array: 13730 return m_it.array_iterator - other.m_it.array_iterator; 13731 13732 case value_t::null: 13733 case value_t::string: 13734 case value_t::boolean: 13735 case value_t::number_integer: 13736 case value_t::number_unsigned: 13737 case value_t::number_float: 13738 case value_t::binary: 13739 case value_t::discarded: 13740 default: 13741 return m_it.primitive_iterator - other.m_it.primitive_iterator; 13742 } 13743 } 13744 13745 /*! 13746 @brief access to successor 13747 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13748 */ 13749 reference operator[](difference_type n) const 13750 { 13751 JSON_ASSERT(m_object != nullptr); 13752 13753 switch (m_object->m_data.m_type) 13754 { 13755 case value_t::object: 13756 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object)); 13757 13758 case value_t::array: 13759 return *std::next(m_it.array_iterator, n); 13760 13761 case value_t::null: 13762 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); 13763 13764 case value_t::string: 13765 case value_t::boolean: 13766 case value_t::number_integer: 13767 case value_t::number_unsigned: 13768 case value_t::number_float: 13769 case value_t::binary: 13770 case value_t::discarded: 13771 default: 13772 { 13773 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) 13774 { 13775 return *m_object; 13776 } 13777 13778 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); 13779 } 13780 } 13781 } 13782 13783 /*! 13784 @brief return the key of an object iterator 13785 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13786 */ 13787 const typename object_t::key_type& key() const 13788 { 13789 JSON_ASSERT(m_object != nullptr); 13790 13791 if (JSON_HEDLEY_LIKELY(m_object->is_object())) 13792 { 13793 return m_it.object_iterator->first; 13794 } 13795 13796 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object)); 13797 } 13798 13799 /*! 13800 @brief return the value of an iterator 13801 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13802 */ 13803 reference value() const 13804 { 13805 return operator*(); 13806 } 13807 13808 JSON_PRIVATE_UNLESS_TESTED: 13809 /// associated JSON instance 13810 pointer m_object = nullptr; 13811 /// the actual iterator of the associated instance 13812 internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {}; 13813 }; 13814 13815 } // namespace detail 13816 NLOHMANN_JSON_NAMESPACE_END 13817 13818 // #include <nlohmann/detail/iterators/iteration_proxy.hpp> 13819 13820 // #include <nlohmann/detail/iterators/json_reverse_iterator.hpp> 13821 // __ _____ _____ _____ 13822 // __| | __| | | | JSON for Modern C++ 13823 // | | |__ | | | | | | version 3.11.3 13824 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 13825 // 13826 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 13827 // SPDX-License-Identifier: MIT 13828 13829 13830 13831 #include <cstddef> // ptrdiff_t 13832 #include <iterator> // reverse_iterator 13833 #include <utility> // declval 13834 13835 // #include <nlohmann/detail/abi_macros.hpp> 13836 13837 13838 NLOHMANN_JSON_NAMESPACE_BEGIN 13839 namespace detail 13840 { 13841 13842 ////////////////////// 13843 // reverse_iterator // 13844 ////////////////////// 13845 13846 /*! 13847 @brief a template for a reverse iterator class 13848 13849 @tparam Base the base iterator type to reverse. Valid types are @ref 13850 iterator (to create @ref reverse_iterator) and @ref const_iterator (to 13851 create @ref const_reverse_iterator). 13852 13853 @requirement The class satisfies the following concept requirements: 13854 - 13855 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): 13856 The iterator that can be moved can be moved in both directions (i.e. 13857 incremented and decremented). 13858 - [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator): 13859 It is possible to write to the pointed-to element (only if @a Base is 13860 @ref iterator). 13861 13862 @since version 1.0.0 13863 */ 13864 template<typename Base> 13865 class json_reverse_iterator : public std::reverse_iterator<Base> 13866 { 13867 public: 13868 using difference_type = std::ptrdiff_t; 13869 /// shortcut to the reverse iterator adapter 13870 using base_iterator = std::reverse_iterator<Base>; 13871 /// the reference type for the pointed-to element 13872 using reference = typename Base::reference; 13873 13874 /// create reverse iterator from iterator 13875 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept 13876 : base_iterator(it) {} 13877 13878 /// create reverse iterator from base class 13879 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} 13880 13881 /// post-increment (it++) 13882 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp) 13883 { 13884 return static_cast<json_reverse_iterator>(base_iterator::operator++(1)); 13885 } 13886 13887 /// pre-increment (++it) 13888 json_reverse_iterator& operator++() 13889 { 13890 return static_cast<json_reverse_iterator&>(base_iterator::operator++()); 13891 } 13892 13893 /// post-decrement (it--) 13894 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp) 13895 { 13896 return static_cast<json_reverse_iterator>(base_iterator::operator--(1)); 13897 } 13898 13899 /// pre-decrement (--it) 13900 json_reverse_iterator& operator--() 13901 { 13902 return static_cast<json_reverse_iterator&>(base_iterator::operator--()); 13903 } 13904 13905 /// add to iterator 13906 json_reverse_iterator& operator+=(difference_type i) 13907 { 13908 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i)); 13909 } 13910 13911 /// add to iterator 13912 json_reverse_iterator operator+(difference_type i) const 13913 { 13914 return static_cast<json_reverse_iterator>(base_iterator::operator+(i)); 13915 } 13916 13917 /// subtract from iterator 13918 json_reverse_iterator operator-(difference_type i) const 13919 { 13920 return static_cast<json_reverse_iterator>(base_iterator::operator-(i)); 13921 } 13922 13923 /// return difference 13924 difference_type operator-(const json_reverse_iterator& other) const 13925 { 13926 return base_iterator(*this) - base_iterator(other); 13927 } 13928 13929 /// access to successor 13930 reference operator[](difference_type n) const 13931 { 13932 return *(this->operator+(n)); 13933 } 13934 13935 /// return the key of an object iterator 13936 auto key() const -> decltype(std::declval<Base>().key()) 13937 { 13938 auto it = --this->base(); 13939 return it.key(); 13940 } 13941 13942 /// return the value of an iterator 13943 reference value() const 13944 { 13945 auto it = --this->base(); 13946 return it.operator * (); 13947 } 13948 }; 13949 13950 } // namespace detail 13951 NLOHMANN_JSON_NAMESPACE_END 13952 13953 // #include <nlohmann/detail/iterators/primitive_iterator.hpp> 13954 13955 // #include <nlohmann/detail/json_custom_base_class.hpp> 13956 // __ _____ _____ _____ 13957 // __| | __| | | | JSON for Modern C++ 13958 // | | |__ | | | | | | version 3.11.3 13959 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 13960 // 13961 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 13962 // SPDX-License-Identifier: MIT 13963 13964 13965 13966 #include <type_traits> // conditional, is_same 13967 13968 // #include <nlohmann/detail/abi_macros.hpp> 13969 13970 13971 NLOHMANN_JSON_NAMESPACE_BEGIN 13972 namespace detail 13973 { 13974 13975 /*! 13976 @brief Default base class of the @ref basic_json class. 13977 13978 So that the correct implementations of the copy / move ctors / assign operators 13979 of @ref basic_json do not require complex case distinctions 13980 (no base class / custom base class used as customization point), 13981 @ref basic_json always has a base class. 13982 By default, this class is used because it is empty and thus has no effect 13983 on the behavior of @ref basic_json. 13984 */ 13985 struct json_default_base {}; 13986 13987 template<class T> 13988 using json_base_class = typename std::conditional < 13989 std::is_same<T, void>::value, 13990 json_default_base, 13991 T 13992 >::type; 13993 13994 } // namespace detail 13995 NLOHMANN_JSON_NAMESPACE_END 13996 13997 // #include <nlohmann/detail/json_pointer.hpp> 13998 // __ _____ _____ _____ 13999 // __| | __| | | | JSON for Modern C++ 14000 // | | |__ | | | | | | version 3.11.3 14001 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 14002 // 14003 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 14004 // SPDX-License-Identifier: MIT 14005 14006 14007 14008 #include <algorithm> // all_of 14009 #include <cctype> // isdigit 14010 #include <cerrno> // errno, ERANGE 14011 #include <cstdlib> // strtoull 14012 #ifndef JSON_NO_IO 14013 #include <iosfwd> // ostream 14014 #endif // JSON_NO_IO 14015 #include <limits> // max 14016 #include <numeric> // accumulate 14017 #include <string> // string 14018 #include <utility> // move 14019 #include <vector> // vector 14020 14021 // #include <nlohmann/detail/exceptions.hpp> 14022 14023 // #include <nlohmann/detail/macro_scope.hpp> 14024 14025 // #include <nlohmann/detail/string_concat.hpp> 14026 14027 // #include <nlohmann/detail/string_escape.hpp> 14028 14029 // #include <nlohmann/detail/value_t.hpp> 14030 14031 14032 NLOHMANN_JSON_NAMESPACE_BEGIN 14033 14034 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document 14035 /// @sa https://json.nlohmann.me/api/json_pointer/ 14036 template<typename RefStringType> 14037 class json_pointer 14038 { 14039 // allow basic_json to access private members 14040 NLOHMANN_BASIC_JSON_TPL_DECLARATION 14041 friend class basic_json; 14042 14043 template<typename> 14044 friend class json_pointer; 14045 14046 template<typename T> 14047 struct string_t_helper 14048 { 14049 using type = T; 14050 }; 14051 14052 NLOHMANN_BASIC_JSON_TPL_DECLARATION 14053 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL> 14054 { 14055 using type = StringType; 14056 }; 14057 14058 public: 14059 // for backwards compatibility accept BasicJsonType 14060 using string_t = typename string_t_helper<RefStringType>::type; 14061 14062 /// @brief create JSON pointer 14063 /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/ 14064 explicit json_pointer(const string_t& s = "") 14065 : reference_tokens(split(s)) 14066 {} 14067 14068 /// @brief return a string representation of the JSON pointer 14069 /// @sa https://json.nlohmann.me/api/json_pointer/to_string/ 14070 string_t to_string() const 14071 { 14072 return std::accumulate(reference_tokens.begin(), reference_tokens.end(), 14073 string_t{}, 14074 [](const string_t& a, const string_t& b) 14075 { 14076 return detail::concat(a, '/', detail::escape(b)); 14077 }); 14078 } 14079 14080 /// @brief return a string representation of the JSON pointer 14081 /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/ 14082 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string()) 14083 operator string_t() const 14084 { 14085 return to_string(); 14086 } 14087 14088 #ifndef JSON_NO_IO 14089 /// @brief write string representation of the JSON pointer to stream 14090 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ 14091 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr) 14092 { 14093 o << ptr.to_string(); 14094 return o; 14095 } 14096 #endif 14097 14098 /// @brief append another JSON pointer at the end of this JSON pointer 14099 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ 14100 json_pointer& operator/=(const json_pointer& ptr) 14101 { 14102 reference_tokens.insert(reference_tokens.end(), 14103 ptr.reference_tokens.begin(), 14104 ptr.reference_tokens.end()); 14105 return *this; 14106 } 14107 14108 /// @brief append an unescaped reference token at the end of this JSON pointer 14109 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ 14110 json_pointer& operator/=(string_t token) 14111 { 14112 push_back(std::move(token)); 14113 return *this; 14114 } 14115 14116 /// @brief append an array index at the end of this JSON pointer 14117 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ 14118 json_pointer& operator/=(std::size_t array_idx) 14119 { 14120 return *this /= std::to_string(array_idx); 14121 } 14122 14123 /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer 14124 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ 14125 friend json_pointer operator/(const json_pointer& lhs, 14126 const json_pointer& rhs) 14127 { 14128 return json_pointer(lhs) /= rhs; 14129 } 14130 14131 /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer 14132 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ 14133 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param) 14134 { 14135 return json_pointer(lhs) /= std::move(token); 14136 } 14137 14138 /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer 14139 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ 14140 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx) 14141 { 14142 return json_pointer(lhs) /= array_idx; 14143 } 14144 14145 /// @brief returns the parent of this JSON pointer 14146 /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/ 14147 json_pointer parent_pointer() const 14148 { 14149 if (empty()) 14150 { 14151 return *this; 14152 } 14153 14154 json_pointer res = *this; 14155 res.pop_back(); 14156 return res; 14157 } 14158 14159 /// @brief remove last reference token 14160 /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/ 14161 void pop_back() 14162 { 14163 if (JSON_HEDLEY_UNLIKELY(empty())) 14164 { 14165 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); 14166 } 14167 14168 reference_tokens.pop_back(); 14169 } 14170 14171 /// @brief return last reference token 14172 /// @sa https://json.nlohmann.me/api/json_pointer/back/ 14173 const string_t& back() const 14174 { 14175 if (JSON_HEDLEY_UNLIKELY(empty())) 14176 { 14177 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); 14178 } 14179 14180 return reference_tokens.back(); 14181 } 14182 14183 /// @brief append an unescaped token at the end of the reference pointer 14184 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ 14185 void push_back(const string_t& token) 14186 { 14187 reference_tokens.push_back(token); 14188 } 14189 14190 /// @brief append an unescaped token at the end of the reference pointer 14191 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ 14192 void push_back(string_t&& token) 14193 { 14194 reference_tokens.push_back(std::move(token)); 14195 } 14196 14197 /// @brief return whether pointer points to the root document 14198 /// @sa https://json.nlohmann.me/api/json_pointer/empty/ 14199 bool empty() const noexcept 14200 { 14201 return reference_tokens.empty(); 14202 } 14203 14204 private: 14205 /*! 14206 @param[in] s reference token to be converted into an array index 14207 14208 @return integer representation of @a s 14209 14210 @throw parse_error.106 if an array index begins with '0' 14211 @throw parse_error.109 if an array index begins not with a digit 14212 @throw out_of_range.404 if string @a s could not be converted to an integer 14213 @throw out_of_range.410 if an array index exceeds size_type 14214 */ 14215 template<typename BasicJsonType> 14216 static typename BasicJsonType::size_type array_index(const string_t& s) 14217 { 14218 using size_type = typename BasicJsonType::size_type; 14219 14220 // error condition (cf. RFC 6901, Sect. 4) 14221 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) 14222 { 14223 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr)); 14224 } 14225 14226 // error condition (cf. RFC 6901, Sect. 4) 14227 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) 14228 { 14229 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr)); 14230 } 14231 14232 const char* p = s.c_str(); 14233 char* p_end = nullptr; 14234 errno = 0; // strtoull doesn't reset errno 14235 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int) 14236 if (p == p_end // invalid input or empty string 14237 || errno == ERANGE // out of range 14238 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read 14239 { 14240 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr)); 14241 } 14242 14243 // only triggered on special platforms (like 32bit), see also 14244 // https://github.com/nlohmann/json/pull/2203 14245 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int) 14246 { 14247 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE 14248 } 14249 14250 return static_cast<size_type>(res); 14251 } 14252 14253 JSON_PRIVATE_UNLESS_TESTED: 14254 json_pointer top() const 14255 { 14256 if (JSON_HEDLEY_UNLIKELY(empty())) 14257 { 14258 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); 14259 } 14260 14261 json_pointer result = *this; 14262 result.reference_tokens = {reference_tokens[0]}; 14263 return result; 14264 } 14265 14266 private: 14267 /*! 14268 @brief create and return a reference to the pointed to value 14269 14270 @complexity Linear in the number of reference tokens. 14271 14272 @throw parse_error.109 if array index is not a number 14273 @throw type_error.313 if value cannot be unflattened 14274 */ 14275 template<typename BasicJsonType> 14276 BasicJsonType& get_and_create(BasicJsonType& j) const 14277 { 14278 auto* result = &j; 14279 14280 // in case no reference tokens exist, return a reference to the JSON value 14281 // j which will be overwritten by a primitive value 14282 for (const auto& reference_token : reference_tokens) 14283 { 14284 switch (result->type()) 14285 { 14286 case detail::value_t::null: 14287 { 14288 if (reference_token == "0") 14289 { 14290 // start a new array if reference token is 0 14291 result = &result->operator[](0); 14292 } 14293 else 14294 { 14295 // start a new object otherwise 14296 result = &result->operator[](reference_token); 14297 } 14298 break; 14299 } 14300 14301 case detail::value_t::object: 14302 { 14303 // create an entry in the object 14304 result = &result->operator[](reference_token); 14305 break; 14306 } 14307 14308 case detail::value_t::array: 14309 { 14310 // create an entry in the array 14311 result = &result->operator[](array_index<BasicJsonType>(reference_token)); 14312 break; 14313 } 14314 14315 /* 14316 The following code is only reached if there exists a reference 14317 token _and_ the current value is primitive. In this case, we have 14318 an error situation, because primitive values may only occur as 14319 single value; that is, with an empty list of reference tokens. 14320 */ 14321 case detail::value_t::string: 14322 case detail::value_t::boolean: 14323 case detail::value_t::number_integer: 14324 case detail::value_t::number_unsigned: 14325 case detail::value_t::number_float: 14326 case detail::value_t::binary: 14327 case detail::value_t::discarded: 14328 default: 14329 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j)); 14330 } 14331 } 14332 14333 return *result; 14334 } 14335 14336 /*! 14337 @brief return a reference to the pointed to value 14338 14339 @note This version does not throw if a value is not present, but tries to 14340 create nested values instead. For instance, calling this function 14341 with pointer `"/this/that"` on a null value is equivalent to calling 14342 `operator[]("this").operator[]("that")` on that value, effectively 14343 changing the null value to an object. 14344 14345 @param[in] ptr a JSON value 14346 14347 @return reference to the JSON value pointed to by the JSON pointer 14348 14349 @complexity Linear in the length of the JSON pointer. 14350 14351 @throw parse_error.106 if an array index begins with '0' 14352 @throw parse_error.109 if an array index was not a number 14353 @throw out_of_range.404 if the JSON pointer can not be resolved 14354 */ 14355 template<typename BasicJsonType> 14356 BasicJsonType& get_unchecked(BasicJsonType* ptr) const 14357 { 14358 for (const auto& reference_token : reference_tokens) 14359 { 14360 // convert null values to arrays or objects before continuing 14361 if (ptr->is_null()) 14362 { 14363 // check if reference token is a number 14364 const bool nums = 14365 std::all_of(reference_token.begin(), reference_token.end(), 14366 [](const unsigned char x) 14367 { 14368 return std::isdigit(x); 14369 }); 14370 14371 // change value to array for numbers or "-" or to object otherwise 14372 *ptr = (nums || reference_token == "-") 14373 ? detail::value_t::array 14374 : detail::value_t::object; 14375 } 14376 14377 switch (ptr->type()) 14378 { 14379 case detail::value_t::object: 14380 { 14381 // use unchecked object access 14382 ptr = &ptr->operator[](reference_token); 14383 break; 14384 } 14385 14386 case detail::value_t::array: 14387 { 14388 if (reference_token == "-") 14389 { 14390 // explicitly treat "-" as index beyond the end 14391 ptr = &ptr->operator[](ptr->m_data.m_value.array->size()); 14392 } 14393 else 14394 { 14395 // convert array index to number; unchecked access 14396 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token)); 14397 } 14398 break; 14399 } 14400 14401 case detail::value_t::null: 14402 case detail::value_t::string: 14403 case detail::value_t::boolean: 14404 case detail::value_t::number_integer: 14405 case detail::value_t::number_unsigned: 14406 case detail::value_t::number_float: 14407 case detail::value_t::binary: 14408 case detail::value_t::discarded: 14409 default: 14410 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); 14411 } 14412 } 14413 14414 return *ptr; 14415 } 14416 14417 /*! 14418 @throw parse_error.106 if an array index begins with '0' 14419 @throw parse_error.109 if an array index was not a number 14420 @throw out_of_range.402 if the array index '-' is used 14421 @throw out_of_range.404 if the JSON pointer can not be resolved 14422 */ 14423 template<typename BasicJsonType> 14424 BasicJsonType& get_checked(BasicJsonType* ptr) const 14425 { 14426 for (const auto& reference_token : reference_tokens) 14427 { 14428 switch (ptr->type()) 14429 { 14430 case detail::value_t::object: 14431 { 14432 // note: at performs range check 14433 ptr = &ptr->at(reference_token); 14434 break; 14435 } 14436 14437 case detail::value_t::array: 14438 { 14439 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) 14440 { 14441 // "-" always fails the range check 14442 JSON_THROW(detail::out_of_range::create(402, detail::concat( 14443 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), 14444 ") is out of range"), ptr)); 14445 } 14446 14447 // note: at performs range check 14448 ptr = &ptr->at(array_index<BasicJsonType>(reference_token)); 14449 break; 14450 } 14451 14452 case detail::value_t::null: 14453 case detail::value_t::string: 14454 case detail::value_t::boolean: 14455 case detail::value_t::number_integer: 14456 case detail::value_t::number_unsigned: 14457 case detail::value_t::number_float: 14458 case detail::value_t::binary: 14459 case detail::value_t::discarded: 14460 default: 14461 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); 14462 } 14463 } 14464 14465 return *ptr; 14466 } 14467 14468 /*! 14469 @brief return a const reference to the pointed to value 14470 14471 @param[in] ptr a JSON value 14472 14473 @return const reference to the JSON value pointed to by the JSON 14474 pointer 14475 14476 @throw parse_error.106 if an array index begins with '0' 14477 @throw parse_error.109 if an array index was not a number 14478 @throw out_of_range.402 if the array index '-' is used 14479 @throw out_of_range.404 if the JSON pointer can not be resolved 14480 */ 14481 template<typename BasicJsonType> 14482 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const 14483 { 14484 for (const auto& reference_token : reference_tokens) 14485 { 14486 switch (ptr->type()) 14487 { 14488 case detail::value_t::object: 14489 { 14490 // use unchecked object access 14491 ptr = &ptr->operator[](reference_token); 14492 break; 14493 } 14494 14495 case detail::value_t::array: 14496 { 14497 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) 14498 { 14499 // "-" cannot be used for const access 14500 JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr)); 14501 } 14502 14503 // use unchecked array access 14504 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token)); 14505 break; 14506 } 14507 14508 case detail::value_t::null: 14509 case detail::value_t::string: 14510 case detail::value_t::boolean: 14511 case detail::value_t::number_integer: 14512 case detail::value_t::number_unsigned: 14513 case detail::value_t::number_float: 14514 case detail::value_t::binary: 14515 case detail::value_t::discarded: 14516 default: 14517 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); 14518 } 14519 } 14520 14521 return *ptr; 14522 } 14523 14524 /*! 14525 @throw parse_error.106 if an array index begins with '0' 14526 @throw parse_error.109 if an array index was not a number 14527 @throw out_of_range.402 if the array index '-' is used 14528 @throw out_of_range.404 if the JSON pointer can not be resolved 14529 */ 14530 template<typename BasicJsonType> 14531 const BasicJsonType& get_checked(const BasicJsonType* ptr) const 14532 { 14533 for (const auto& reference_token : reference_tokens) 14534 { 14535 switch (ptr->type()) 14536 { 14537 case detail::value_t::object: 14538 { 14539 // note: at performs range check 14540 ptr = &ptr->at(reference_token); 14541 break; 14542 } 14543 14544 case detail::value_t::array: 14545 { 14546 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) 14547 { 14548 // "-" always fails the range check 14549 JSON_THROW(detail::out_of_range::create(402, detail::concat( 14550 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), 14551 ") is out of range"), ptr)); 14552 } 14553 14554 // note: at performs range check 14555 ptr = &ptr->at(array_index<BasicJsonType>(reference_token)); 14556 break; 14557 } 14558 14559 case detail::value_t::null: 14560 case detail::value_t::string: 14561 case detail::value_t::boolean: 14562 case detail::value_t::number_integer: 14563 case detail::value_t::number_unsigned: 14564 case detail::value_t::number_float: 14565 case detail::value_t::binary: 14566 case detail::value_t::discarded: 14567 default: 14568 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); 14569 } 14570 } 14571 14572 return *ptr; 14573 } 14574 14575 /*! 14576 @throw parse_error.106 if an array index begins with '0' 14577 @throw parse_error.109 if an array index was not a number 14578 */ 14579 template<typename BasicJsonType> 14580 bool contains(const BasicJsonType* ptr) const 14581 { 14582 for (const auto& reference_token : reference_tokens) 14583 { 14584 switch (ptr->type()) 14585 { 14586 case detail::value_t::object: 14587 { 14588 if (!ptr->contains(reference_token)) 14589 { 14590 // we did not find the key in the object 14591 return false; 14592 } 14593 14594 ptr = &ptr->operator[](reference_token); 14595 break; 14596 } 14597 14598 case detail::value_t::array: 14599 { 14600 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) 14601 { 14602 // "-" always fails the range check 14603 return false; 14604 } 14605 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9"))) 14606 { 14607 // invalid char 14608 return false; 14609 } 14610 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) 14611 { 14612 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9'))) 14613 { 14614 // first char should be between '1' and '9' 14615 return false; 14616 } 14617 for (std::size_t i = 1; i < reference_token.size(); i++) 14618 { 14619 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9'))) 14620 { 14621 // other char should be between '0' and '9' 14622 return false; 14623 } 14624 } 14625 } 14626 14627 const auto idx = array_index<BasicJsonType>(reference_token); 14628 if (idx >= ptr->size()) 14629 { 14630 // index out of range 14631 return false; 14632 } 14633 14634 ptr = &ptr->operator[](idx); 14635 break; 14636 } 14637 14638 case detail::value_t::null: 14639 case detail::value_t::string: 14640 case detail::value_t::boolean: 14641 case detail::value_t::number_integer: 14642 case detail::value_t::number_unsigned: 14643 case detail::value_t::number_float: 14644 case detail::value_t::binary: 14645 case detail::value_t::discarded: 14646 default: 14647 { 14648 // we do not expect primitive values if there is still a 14649 // reference token to process 14650 return false; 14651 } 14652 } 14653 } 14654 14655 // no reference token left means we found a primitive value 14656 return true; 14657 } 14658 14659 /*! 14660 @brief split the string input to reference tokens 14661 14662 @note This function is only called by the json_pointer constructor. 14663 All exceptions below are documented there. 14664 14665 @throw parse_error.107 if the pointer is not empty or begins with '/' 14666 @throw parse_error.108 if character '~' is not followed by '0' or '1' 14667 */ 14668 static std::vector<string_t> split(const string_t& reference_string) 14669 { 14670 std::vector<string_t> result; 14671 14672 // special case: empty reference string -> no reference tokens 14673 if (reference_string.empty()) 14674 { 14675 return result; 14676 } 14677 14678 // check if nonempty reference string begins with slash 14679 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) 14680 { 14681 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr)); 14682 } 14683 14684 // extract the reference tokens: 14685 // - slash: position of the last read slash (or end of string) 14686 // - start: position after the previous slash 14687 for ( 14688 // search for the first slash after the first character 14689 std::size_t slash = reference_string.find_first_of('/', 1), 14690 // set the beginning of the first reference token 14691 start = 1; 14692 // we can stop if start == 0 (if slash == string_t::npos) 14693 start != 0; 14694 // set the beginning of the next reference token 14695 // (will eventually be 0 if slash == string_t::npos) 14696 start = (slash == string_t::npos) ? 0 : slash + 1, 14697 // find next slash 14698 slash = reference_string.find_first_of('/', start)) 14699 { 14700 // use the text between the beginning of the reference token 14701 // (start) and the last slash (slash). 14702 auto reference_token = reference_string.substr(start, slash - start); 14703 14704 // check reference tokens are properly escaped 14705 for (std::size_t pos = reference_token.find_first_of('~'); 14706 pos != string_t::npos; 14707 pos = reference_token.find_first_of('~', pos + 1)) 14708 { 14709 JSON_ASSERT(reference_token[pos] == '~'); 14710 14711 // ~ must be followed by 0 or 1 14712 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || 14713 (reference_token[pos + 1] != '0' && 14714 reference_token[pos + 1] != '1'))) 14715 { 14716 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr)); 14717 } 14718 } 14719 14720 // finally, store the reference token 14721 detail::unescape(reference_token); 14722 result.push_back(reference_token); 14723 } 14724 14725 return result; 14726 } 14727 14728 private: 14729 /*! 14730 @param[in] reference_string the reference string to the current value 14731 @param[in] value the value to consider 14732 @param[in,out] result the result object to insert values to 14733 14734 @note Empty objects or arrays are flattened to `null`. 14735 */ 14736 template<typename BasicJsonType> 14737 static void flatten(const string_t& reference_string, 14738 const BasicJsonType& value, 14739 BasicJsonType& result) 14740 { 14741 switch (value.type()) 14742 { 14743 case detail::value_t::array: 14744 { 14745 if (value.m_data.m_value.array->empty()) 14746 { 14747 // flatten empty array as null 14748 result[reference_string] = nullptr; 14749 } 14750 else 14751 { 14752 // iterate array and use index as reference string 14753 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i) 14754 { 14755 flatten(detail::concat(reference_string, '/', std::to_string(i)), 14756 value.m_data.m_value.array->operator[](i), result); 14757 } 14758 } 14759 break; 14760 } 14761 14762 case detail::value_t::object: 14763 { 14764 if (value.m_data.m_value.object->empty()) 14765 { 14766 // flatten empty object as null 14767 result[reference_string] = nullptr; 14768 } 14769 else 14770 { 14771 // iterate object and use keys as reference string 14772 for (const auto& element : *value.m_data.m_value.object) 14773 { 14774 flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result); 14775 } 14776 } 14777 break; 14778 } 14779 14780 case detail::value_t::null: 14781 case detail::value_t::string: 14782 case detail::value_t::boolean: 14783 case detail::value_t::number_integer: 14784 case detail::value_t::number_unsigned: 14785 case detail::value_t::number_float: 14786 case detail::value_t::binary: 14787 case detail::value_t::discarded: 14788 default: 14789 { 14790 // add primitive value with its reference string 14791 result[reference_string] = value; 14792 break; 14793 } 14794 } 14795 } 14796 14797 /*! 14798 @param[in] value flattened JSON 14799 14800 @return unflattened JSON 14801 14802 @throw parse_error.109 if array index is not a number 14803 @throw type_error.314 if value is not an object 14804 @throw type_error.315 if object values are not primitive 14805 @throw type_error.313 if value cannot be unflattened 14806 */ 14807 template<typename BasicJsonType> 14808 static BasicJsonType 14809 unflatten(const BasicJsonType& value) 14810 { 14811 if (JSON_HEDLEY_UNLIKELY(!value.is_object())) 14812 { 14813 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value)); 14814 } 14815 14816 BasicJsonType result; 14817 14818 // iterate the JSON object values 14819 for (const auto& element : *value.m_data.m_value.object) 14820 { 14821 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) 14822 { 14823 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second)); 14824 } 14825 14826 // assign value to reference pointed to by JSON pointer; Note that if 14827 // the JSON pointer is "" (i.e., points to the whole value), function 14828 // get_and_create returns a reference to result itself. An assignment 14829 // will then create a primitive value. 14830 json_pointer(element.first).get_and_create(result) = element.second; 14831 } 14832 14833 return result; 14834 } 14835 14836 // can't use conversion operator because of ambiguity 14837 json_pointer<string_t> convert() const& 14838 { 14839 json_pointer<string_t> result; 14840 result.reference_tokens = reference_tokens; 14841 return result; 14842 } 14843 14844 json_pointer<string_t> convert()&& 14845 { 14846 json_pointer<string_t> result; 14847 result.reference_tokens = std::move(reference_tokens); 14848 return result; 14849 } 14850 14851 public: 14852 #if JSON_HAS_THREE_WAY_COMPARISON 14853 /// @brief compares two JSON pointers for equality 14854 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 14855 template<typename RefStringTypeRhs> 14856 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept 14857 { 14858 return reference_tokens == rhs.reference_tokens; 14859 } 14860 14861 /// @brief compares JSON pointer and string for equality 14862 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 14863 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer)) 14864 bool operator==(const string_t& rhs) const 14865 { 14866 return *this == json_pointer(rhs); 14867 } 14868 14869 /// @brief 3-way compares two JSON pointers 14870 template<typename RefStringTypeRhs> 14871 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD* 14872 { 14873 return reference_tokens <=> rhs.reference_tokens; // *NOPAD* 14874 } 14875 #else 14876 /// @brief compares two JSON pointers for equality 14877 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 14878 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14879 // NOLINTNEXTLINE(readability-redundant-declaration) 14880 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs, 14881 const json_pointer<RefStringTypeRhs>& rhs) noexcept; 14882 14883 /// @brief compares JSON pointer and string for equality 14884 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 14885 template<typename RefStringTypeLhs, typename StringType> 14886 // NOLINTNEXTLINE(readability-redundant-declaration) 14887 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs, 14888 const StringType& rhs); 14889 14890 /// @brief compares string and JSON pointer for equality 14891 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 14892 template<typename RefStringTypeRhs, typename StringType> 14893 // NOLINTNEXTLINE(readability-redundant-declaration) 14894 friend bool operator==(const StringType& lhs, 14895 const json_pointer<RefStringTypeRhs>& rhs); 14896 14897 /// @brief compares two JSON pointers for inequality 14898 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ 14899 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14900 // NOLINTNEXTLINE(readability-redundant-declaration) 14901 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, 14902 const json_pointer<RefStringTypeRhs>& rhs) noexcept; 14903 14904 /// @brief compares JSON pointer and string for inequality 14905 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ 14906 template<typename RefStringTypeLhs, typename StringType> 14907 // NOLINTNEXTLINE(readability-redundant-declaration) 14908 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, 14909 const StringType& rhs); 14910 14911 /// @brief compares string and JSON pointer for inequality 14912 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ 14913 template<typename RefStringTypeRhs, typename StringType> 14914 // NOLINTNEXTLINE(readability-redundant-declaration) 14915 friend bool operator!=(const StringType& lhs, 14916 const json_pointer<RefStringTypeRhs>& rhs); 14917 14918 /// @brief compares two JSON pointer for less-than 14919 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14920 // NOLINTNEXTLINE(readability-redundant-declaration) 14921 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs, 14922 const json_pointer<RefStringTypeRhs>& rhs) noexcept; 14923 #endif 14924 14925 private: 14926 /// the reference tokens 14927 std::vector<string_t> reference_tokens; 14928 }; 14929 14930 #if !JSON_HAS_THREE_WAY_COMPARISON 14931 // functions cannot be defined inside class due to ODR violations 14932 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14933 inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, 14934 const json_pointer<RefStringTypeRhs>& rhs) noexcept 14935 { 14936 return lhs.reference_tokens == rhs.reference_tokens; 14937 } 14938 14939 template<typename RefStringTypeLhs, 14940 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t> 14941 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) 14942 inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, 14943 const StringType& rhs) 14944 { 14945 return lhs == json_pointer<RefStringTypeLhs>(rhs); 14946 } 14947 14948 template<typename RefStringTypeRhs, 14949 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t> 14950 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) 14951 inline bool operator==(const StringType& lhs, 14952 const json_pointer<RefStringTypeRhs>& rhs) 14953 { 14954 return json_pointer<RefStringTypeRhs>(lhs) == rhs; 14955 } 14956 14957 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14958 inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, 14959 const json_pointer<RefStringTypeRhs>& rhs) noexcept 14960 { 14961 return !(lhs == rhs); 14962 } 14963 14964 template<typename RefStringTypeLhs, 14965 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t> 14966 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) 14967 inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, 14968 const StringType& rhs) 14969 { 14970 return !(lhs == rhs); 14971 } 14972 14973 template<typename RefStringTypeRhs, 14974 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t> 14975 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) 14976 inline bool operator!=(const StringType& lhs, 14977 const json_pointer<RefStringTypeRhs>& rhs) 14978 { 14979 return !(lhs == rhs); 14980 } 14981 14982 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14983 inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs, 14984 const json_pointer<RefStringTypeRhs>& rhs) noexcept 14985 { 14986 return lhs.reference_tokens < rhs.reference_tokens; 14987 } 14988 #endif 14989 14990 NLOHMANN_JSON_NAMESPACE_END 14991 14992 // #include <nlohmann/detail/json_ref.hpp> 14993 // __ _____ _____ _____ 14994 // __| | __| | | | JSON for Modern C++ 14995 // | | |__ | | | | | | version 3.11.3 14996 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 14997 // 14998 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 14999 // SPDX-License-Identifier: MIT 15000 15001 15002 15003 #include <initializer_list> 15004 #include <utility> 15005 15006 // #include <nlohmann/detail/abi_macros.hpp> 15007 15008 // #include <nlohmann/detail/meta/type_traits.hpp> 15009 15010 15011 NLOHMANN_JSON_NAMESPACE_BEGIN 15012 namespace detail 15013 { 15014 15015 template<typename BasicJsonType> 15016 class json_ref 15017 { 15018 public: 15019 using value_type = BasicJsonType; 15020 15021 json_ref(value_type&& value) 15022 : owned_value(std::move(value)) 15023 {} 15024 15025 json_ref(const value_type& value) 15026 : value_ref(&value) 15027 {} 15028 15029 json_ref(std::initializer_list<json_ref> init) 15030 : owned_value(init) 15031 {} 15032 15033 template < 15034 class... Args, 15035 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 > 15036 json_ref(Args && ... args) 15037 : owned_value(std::forward<Args>(args)...) 15038 {} 15039 15040 // class should be movable only 15041 json_ref(json_ref&&) noexcept = default; 15042 json_ref(const json_ref&) = delete; 15043 json_ref& operator=(const json_ref&) = delete; 15044 json_ref& operator=(json_ref&&) = delete; 15045 ~json_ref() = default; 15046 15047 value_type moved_or_copied() const 15048 { 15049 if (value_ref == nullptr) 15050 { 15051 return std::move(owned_value); 15052 } 15053 return *value_ref; 15054 } 15055 15056 value_type const& operator*() const 15057 { 15058 return value_ref ? *value_ref : owned_value; 15059 } 15060 15061 value_type const* operator->() const 15062 { 15063 return &** this; 15064 } 15065 15066 private: 15067 mutable value_type owned_value = nullptr; 15068 value_type const* value_ref = nullptr; 15069 }; 15070 15071 } // namespace detail 15072 NLOHMANN_JSON_NAMESPACE_END 15073 15074 // #include <nlohmann/detail/macro_scope.hpp> 15075 15076 // #include <nlohmann/detail/string_concat.hpp> 15077 15078 // #include <nlohmann/detail/string_escape.hpp> 15079 15080 // #include <nlohmann/detail/meta/cpp_future.hpp> 15081 15082 // #include <nlohmann/detail/meta/type_traits.hpp> 15083 15084 // #include <nlohmann/detail/output/binary_writer.hpp> 15085 // __ _____ _____ _____ 15086 // __| | __| | | | JSON for Modern C++ 15087 // | | |__ | | | | | | version 3.11.3 15088 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 15089 // 15090 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 15091 // SPDX-License-Identifier: MIT 15092 15093 15094 15095 #include <algorithm> // reverse 15096 #include <array> // array 15097 #include <map> // map 15098 #include <cmath> // isnan, isinf 15099 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t 15100 #include <cstring> // memcpy 15101 #include <limits> // numeric_limits 15102 #include <string> // string 15103 #include <utility> // move 15104 #include <vector> // vector 15105 15106 // #include <nlohmann/detail/input/binary_reader.hpp> 15107 15108 // #include <nlohmann/detail/macro_scope.hpp> 15109 15110 // #include <nlohmann/detail/output/output_adapters.hpp> 15111 // __ _____ _____ _____ 15112 // __| | __| | | | JSON for Modern C++ 15113 // | | |__ | | | | | | version 3.11.3 15114 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 15115 // 15116 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 15117 // SPDX-License-Identifier: MIT 15118 15119 15120 15121 #include <algorithm> // copy 15122 #include <cstddef> // size_t 15123 #include <iterator> // back_inserter 15124 #include <memory> // shared_ptr, make_shared 15125 #include <string> // basic_string 15126 #include <vector> // vector 15127 15128 #ifndef JSON_NO_IO 15129 #include <ios> // streamsize 15130 #include <ostream> // basic_ostream 15131 #endif // JSON_NO_IO 15132 15133 // #include <nlohmann/detail/macro_scope.hpp> 15134 15135 15136 NLOHMANN_JSON_NAMESPACE_BEGIN 15137 namespace detail 15138 { 15139 15140 /// abstract output adapter interface 15141 template<typename CharType> struct output_adapter_protocol 15142 { 15143 virtual void write_character(CharType c) = 0; 15144 virtual void write_characters(const CharType* s, std::size_t length) = 0; 15145 virtual ~output_adapter_protocol() = default; 15146 15147 output_adapter_protocol() = default; 15148 output_adapter_protocol(const output_adapter_protocol&) = default; 15149 output_adapter_protocol(output_adapter_protocol&&) noexcept = default; 15150 output_adapter_protocol& operator=(const output_adapter_protocol&) = default; 15151 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default; 15152 }; 15153 15154 /// a type to simplify interfaces 15155 template<typename CharType> 15156 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>; 15157 15158 /// output adapter for byte vectors 15159 template<typename CharType, typename AllocatorType = std::allocator<CharType>> 15160 class output_vector_adapter : public output_adapter_protocol<CharType> 15161 { 15162 public: 15163 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept 15164 : v(vec) 15165 {} 15166 15167 void write_character(CharType c) override 15168 { 15169 v.push_back(c); 15170 } 15171 15172 JSON_HEDLEY_NON_NULL(2) 15173 void write_characters(const CharType* s, std::size_t length) override 15174 { 15175 v.insert(v.end(), s, s + length); 15176 } 15177 15178 private: 15179 std::vector<CharType, AllocatorType>& v; 15180 }; 15181 15182 #ifndef JSON_NO_IO 15183 /// output adapter for output streams 15184 template<typename CharType> 15185 class output_stream_adapter : public output_adapter_protocol<CharType> 15186 { 15187 public: 15188 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept 15189 : stream(s) 15190 {} 15191 15192 void write_character(CharType c) override 15193 { 15194 stream.put(c); 15195 } 15196 15197 JSON_HEDLEY_NON_NULL(2) 15198 void write_characters(const CharType* s, std::size_t length) override 15199 { 15200 stream.write(s, static_cast<std::streamsize>(length)); 15201 } 15202 15203 private: 15204 std::basic_ostream<CharType>& stream; 15205 }; 15206 #endif // JSON_NO_IO 15207 15208 /// output adapter for basic_string 15209 template<typename CharType, typename StringType = std::basic_string<CharType>> 15210 class output_string_adapter : public output_adapter_protocol<CharType> 15211 { 15212 public: 15213 explicit output_string_adapter(StringType& s) noexcept 15214 : str(s) 15215 {} 15216 15217 void write_character(CharType c) override 15218 { 15219 str.push_back(c); 15220 } 15221 15222 JSON_HEDLEY_NON_NULL(2) 15223 void write_characters(const CharType* s, std::size_t length) override 15224 { 15225 str.append(s, length); 15226 } 15227 15228 private: 15229 StringType& str; 15230 }; 15231 15232 template<typename CharType, typename StringType = std::basic_string<CharType>> 15233 class output_adapter 15234 { 15235 public: 15236 template<typename AllocatorType = std::allocator<CharType>> 15237 output_adapter(std::vector<CharType, AllocatorType>& vec) 15238 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {} 15239 15240 #ifndef JSON_NO_IO 15241 output_adapter(std::basic_ostream<CharType>& s) 15242 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {} 15243 #endif // JSON_NO_IO 15244 15245 output_adapter(StringType& s) 15246 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {} 15247 15248 operator output_adapter_t<CharType>() 15249 { 15250 return oa; 15251 } 15252 15253 private: 15254 output_adapter_t<CharType> oa = nullptr; 15255 }; 15256 15257 } // namespace detail 15258 NLOHMANN_JSON_NAMESPACE_END 15259 15260 // #include <nlohmann/detail/string_concat.hpp> 15261 15262 15263 NLOHMANN_JSON_NAMESPACE_BEGIN 15264 namespace detail 15265 { 15266 15267 /////////////////// 15268 // binary writer // 15269 /////////////////// 15270 15271 /*! 15272 @brief serialization to CBOR and MessagePack values 15273 */ 15274 template<typename BasicJsonType, typename CharType> 15275 class binary_writer 15276 { 15277 using string_t = typename BasicJsonType::string_t; 15278 using binary_t = typename BasicJsonType::binary_t; 15279 using number_float_t = typename BasicJsonType::number_float_t; 15280 15281 public: 15282 /*! 15283 @brief create a binary writer 15284 15285 @param[in] adapter output adapter to write to 15286 */ 15287 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter)) 15288 { 15289 JSON_ASSERT(oa); 15290 } 15291 15292 /*! 15293 @param[in] j JSON value to serialize 15294 @pre j.type() == value_t::object 15295 */ 15296 void write_bson(const BasicJsonType& j) 15297 { 15298 switch (j.type()) 15299 { 15300 case value_t::object: 15301 { 15302 write_bson_object(*j.m_data.m_value.object); 15303 break; 15304 } 15305 15306 case value_t::null: 15307 case value_t::array: 15308 case value_t::string: 15309 case value_t::boolean: 15310 case value_t::number_integer: 15311 case value_t::number_unsigned: 15312 case value_t::number_float: 15313 case value_t::binary: 15314 case value_t::discarded: 15315 default: 15316 { 15317 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j)); 15318 } 15319 } 15320 } 15321 15322 /*! 15323 @param[in] j JSON value to serialize 15324 */ 15325 void write_cbor(const BasicJsonType& j) 15326 { 15327 switch (j.type()) 15328 { 15329 case value_t::null: 15330 { 15331 oa->write_character(to_char_type(0xF6)); 15332 break; 15333 } 15334 15335 case value_t::boolean: 15336 { 15337 oa->write_character(j.m_data.m_value.boolean 15338 ? to_char_type(0xF5) 15339 : to_char_type(0xF4)); 15340 break; 15341 } 15342 15343 case value_t::number_integer: 15344 { 15345 if (j.m_data.m_value.number_integer >= 0) 15346 { 15347 // CBOR does not differentiate between positive signed 15348 // integers and unsigned integers. Therefore, we used the 15349 // code from the value_t::number_unsigned case here. 15350 if (j.m_data.m_value.number_integer <= 0x17) 15351 { 15352 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); 15353 } 15354 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)()) 15355 { 15356 oa->write_character(to_char_type(0x18)); 15357 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); 15358 } 15359 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()) 15360 { 15361 oa->write_character(to_char_type(0x19)); 15362 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer)); 15363 } 15364 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()) 15365 { 15366 oa->write_character(to_char_type(0x1A)); 15367 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer)); 15368 } 15369 else 15370 { 15371 oa->write_character(to_char_type(0x1B)); 15372 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer)); 15373 } 15374 } 15375 else 15376 { 15377 // The conversions below encode the sign in the first 15378 // byte, and the value is converted to a positive number. 15379 const auto positive_number = -1 - j.m_data.m_value.number_integer; 15380 if (j.m_data.m_value.number_integer >= -24) 15381 { 15382 write_number(static_cast<std::uint8_t>(0x20 + positive_number)); 15383 } 15384 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)()) 15385 { 15386 oa->write_character(to_char_type(0x38)); 15387 write_number(static_cast<std::uint8_t>(positive_number)); 15388 } 15389 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)()) 15390 { 15391 oa->write_character(to_char_type(0x39)); 15392 write_number(static_cast<std::uint16_t>(positive_number)); 15393 } 15394 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)()) 15395 { 15396 oa->write_character(to_char_type(0x3A)); 15397 write_number(static_cast<std::uint32_t>(positive_number)); 15398 } 15399 else 15400 { 15401 oa->write_character(to_char_type(0x3B)); 15402 write_number(static_cast<std::uint64_t>(positive_number)); 15403 } 15404 } 15405 break; 15406 } 15407 15408 case value_t::number_unsigned: 15409 { 15410 if (j.m_data.m_value.number_unsigned <= 0x17) 15411 { 15412 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned)); 15413 } 15414 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) 15415 { 15416 oa->write_character(to_char_type(0x18)); 15417 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned)); 15418 } 15419 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) 15420 { 15421 oa->write_character(to_char_type(0x19)); 15422 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned)); 15423 } 15424 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) 15425 { 15426 oa->write_character(to_char_type(0x1A)); 15427 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned)); 15428 } 15429 else 15430 { 15431 oa->write_character(to_char_type(0x1B)); 15432 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned)); 15433 } 15434 break; 15435 } 15436 15437 case value_t::number_float: 15438 { 15439 if (std::isnan(j.m_data.m_value.number_float)) 15440 { 15441 // NaN is 0xf97e00 in CBOR 15442 oa->write_character(to_char_type(0xF9)); 15443 oa->write_character(to_char_type(0x7E)); 15444 oa->write_character(to_char_type(0x00)); 15445 } 15446 else if (std::isinf(j.m_data.m_value.number_float)) 15447 { 15448 // Infinity is 0xf97c00, -Infinity is 0xf9fc00 15449 oa->write_character(to_char_type(0xf9)); 15450 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); 15451 oa->write_character(to_char_type(0x00)); 15452 } 15453 else 15454 { 15455 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor); 15456 } 15457 break; 15458 } 15459 15460 case value_t::string: 15461 { 15462 // step 1: write control byte and the string length 15463 const auto N = j.m_data.m_value.string->size(); 15464 if (N <= 0x17) 15465 { 15466 write_number(static_cast<std::uint8_t>(0x60 + N)); 15467 } 15468 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15469 { 15470 oa->write_character(to_char_type(0x78)); 15471 write_number(static_cast<std::uint8_t>(N)); 15472 } 15473 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15474 { 15475 oa->write_character(to_char_type(0x79)); 15476 write_number(static_cast<std::uint16_t>(N)); 15477 } 15478 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15479 { 15480 oa->write_character(to_char_type(0x7A)); 15481 write_number(static_cast<std::uint32_t>(N)); 15482 } 15483 // LCOV_EXCL_START 15484 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) 15485 { 15486 oa->write_character(to_char_type(0x7B)); 15487 write_number(static_cast<std::uint64_t>(N)); 15488 } 15489 // LCOV_EXCL_STOP 15490 15491 // step 2: write the string 15492 oa->write_characters( 15493 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()), 15494 j.m_data.m_value.string->size()); 15495 break; 15496 } 15497 15498 case value_t::array: 15499 { 15500 // step 1: write control byte and the array size 15501 const auto N = j.m_data.m_value.array->size(); 15502 if (N <= 0x17) 15503 { 15504 write_number(static_cast<std::uint8_t>(0x80 + N)); 15505 } 15506 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15507 { 15508 oa->write_character(to_char_type(0x98)); 15509 write_number(static_cast<std::uint8_t>(N)); 15510 } 15511 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15512 { 15513 oa->write_character(to_char_type(0x99)); 15514 write_number(static_cast<std::uint16_t>(N)); 15515 } 15516 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15517 { 15518 oa->write_character(to_char_type(0x9A)); 15519 write_number(static_cast<std::uint32_t>(N)); 15520 } 15521 // LCOV_EXCL_START 15522 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) 15523 { 15524 oa->write_character(to_char_type(0x9B)); 15525 write_number(static_cast<std::uint64_t>(N)); 15526 } 15527 // LCOV_EXCL_STOP 15528 15529 // step 2: write each element 15530 for (const auto& el : *j.m_data.m_value.array) 15531 { 15532 write_cbor(el); 15533 } 15534 break; 15535 } 15536 15537 case value_t::binary: 15538 { 15539 if (j.m_data.m_value.binary->has_subtype()) 15540 { 15541 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)()) 15542 { 15543 write_number(static_cast<std::uint8_t>(0xd8)); 15544 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype())); 15545 } 15546 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)()) 15547 { 15548 write_number(static_cast<std::uint8_t>(0xd9)); 15549 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype())); 15550 } 15551 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)()) 15552 { 15553 write_number(static_cast<std::uint8_t>(0xda)); 15554 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype())); 15555 } 15556 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)()) 15557 { 15558 write_number(static_cast<std::uint8_t>(0xdb)); 15559 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype())); 15560 } 15561 } 15562 15563 // step 1: write control byte and the binary array size 15564 const auto N = j.m_data.m_value.binary->size(); 15565 if (N <= 0x17) 15566 { 15567 write_number(static_cast<std::uint8_t>(0x40 + N)); 15568 } 15569 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15570 { 15571 oa->write_character(to_char_type(0x58)); 15572 write_number(static_cast<std::uint8_t>(N)); 15573 } 15574 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15575 { 15576 oa->write_character(to_char_type(0x59)); 15577 write_number(static_cast<std::uint16_t>(N)); 15578 } 15579 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15580 { 15581 oa->write_character(to_char_type(0x5A)); 15582 write_number(static_cast<std::uint32_t>(N)); 15583 } 15584 // LCOV_EXCL_START 15585 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) 15586 { 15587 oa->write_character(to_char_type(0x5B)); 15588 write_number(static_cast<std::uint64_t>(N)); 15589 } 15590 // LCOV_EXCL_STOP 15591 15592 // step 2: write each element 15593 oa->write_characters( 15594 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()), 15595 N); 15596 15597 break; 15598 } 15599 15600 case value_t::object: 15601 { 15602 // step 1: write control byte and the object size 15603 const auto N = j.m_data.m_value.object->size(); 15604 if (N <= 0x17) 15605 { 15606 write_number(static_cast<std::uint8_t>(0xA0 + N)); 15607 } 15608 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15609 { 15610 oa->write_character(to_char_type(0xB8)); 15611 write_number(static_cast<std::uint8_t>(N)); 15612 } 15613 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15614 { 15615 oa->write_character(to_char_type(0xB9)); 15616 write_number(static_cast<std::uint16_t>(N)); 15617 } 15618 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15619 { 15620 oa->write_character(to_char_type(0xBA)); 15621 write_number(static_cast<std::uint32_t>(N)); 15622 } 15623 // LCOV_EXCL_START 15624 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) 15625 { 15626 oa->write_character(to_char_type(0xBB)); 15627 write_number(static_cast<std::uint64_t>(N)); 15628 } 15629 // LCOV_EXCL_STOP 15630 15631 // step 2: write each element 15632 for (const auto& el : *j.m_data.m_value.object) 15633 { 15634 write_cbor(el.first); 15635 write_cbor(el.second); 15636 } 15637 break; 15638 } 15639 15640 case value_t::discarded: 15641 default: 15642 break; 15643 } 15644 } 15645 15646 /*! 15647 @param[in] j JSON value to serialize 15648 */ 15649 void write_msgpack(const BasicJsonType& j) 15650 { 15651 switch (j.type()) 15652 { 15653 case value_t::null: // nil 15654 { 15655 oa->write_character(to_char_type(0xC0)); 15656 break; 15657 } 15658 15659 case value_t::boolean: // true and false 15660 { 15661 oa->write_character(j.m_data.m_value.boolean 15662 ? to_char_type(0xC3) 15663 : to_char_type(0xC2)); 15664 break; 15665 } 15666 15667 case value_t::number_integer: 15668 { 15669 if (j.m_data.m_value.number_integer >= 0) 15670 { 15671 // MessagePack does not differentiate between positive 15672 // signed integers and unsigned integers. Therefore, we used 15673 // the code from the value_t::number_unsigned case here. 15674 if (j.m_data.m_value.number_unsigned < 128) 15675 { 15676 // positive fixnum 15677 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); 15678 } 15679 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) 15680 { 15681 // uint 8 15682 oa->write_character(to_char_type(0xCC)); 15683 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); 15684 } 15685 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) 15686 { 15687 // uint 16 15688 oa->write_character(to_char_type(0xCD)); 15689 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer)); 15690 } 15691 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) 15692 { 15693 // uint 32 15694 oa->write_character(to_char_type(0xCE)); 15695 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer)); 15696 } 15697 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) 15698 { 15699 // uint 64 15700 oa->write_character(to_char_type(0xCF)); 15701 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer)); 15702 } 15703 } 15704 else 15705 { 15706 if (j.m_data.m_value.number_integer >= -32) 15707 { 15708 // negative fixnum 15709 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer)); 15710 } 15711 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() && 15712 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)()) 15713 { 15714 // int 8 15715 oa->write_character(to_char_type(0xD0)); 15716 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer)); 15717 } 15718 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() && 15719 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)()) 15720 { 15721 // int 16 15722 oa->write_character(to_char_type(0xD1)); 15723 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer)); 15724 } 15725 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() && 15726 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)()) 15727 { 15728 // int 32 15729 oa->write_character(to_char_type(0xD2)); 15730 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer)); 15731 } 15732 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() && 15733 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)()) 15734 { 15735 // int 64 15736 oa->write_character(to_char_type(0xD3)); 15737 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer)); 15738 } 15739 } 15740 break; 15741 } 15742 15743 case value_t::number_unsigned: 15744 { 15745 if (j.m_data.m_value.number_unsigned < 128) 15746 { 15747 // positive fixnum 15748 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); 15749 } 15750 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) 15751 { 15752 // uint 8 15753 oa->write_character(to_char_type(0xCC)); 15754 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); 15755 } 15756 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) 15757 { 15758 // uint 16 15759 oa->write_character(to_char_type(0xCD)); 15760 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer)); 15761 } 15762 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) 15763 { 15764 // uint 32 15765 oa->write_character(to_char_type(0xCE)); 15766 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer)); 15767 } 15768 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) 15769 { 15770 // uint 64 15771 oa->write_character(to_char_type(0xCF)); 15772 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer)); 15773 } 15774 break; 15775 } 15776 15777 case value_t::number_float: 15778 { 15779 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack); 15780 break; 15781 } 15782 15783 case value_t::string: 15784 { 15785 // step 1: write control byte and the string length 15786 const auto N = j.m_data.m_value.string->size(); 15787 if (N <= 31) 15788 { 15789 // fixstr 15790 write_number(static_cast<std::uint8_t>(0xA0 | N)); 15791 } 15792 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15793 { 15794 // str 8 15795 oa->write_character(to_char_type(0xD9)); 15796 write_number(static_cast<std::uint8_t>(N)); 15797 } 15798 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15799 { 15800 // str 16 15801 oa->write_character(to_char_type(0xDA)); 15802 write_number(static_cast<std::uint16_t>(N)); 15803 } 15804 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15805 { 15806 // str 32 15807 oa->write_character(to_char_type(0xDB)); 15808 write_number(static_cast<std::uint32_t>(N)); 15809 } 15810 15811 // step 2: write the string 15812 oa->write_characters( 15813 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()), 15814 j.m_data.m_value.string->size()); 15815 break; 15816 } 15817 15818 case value_t::array: 15819 { 15820 // step 1: write control byte and the array size 15821 const auto N = j.m_data.m_value.array->size(); 15822 if (N <= 15) 15823 { 15824 // fixarray 15825 write_number(static_cast<std::uint8_t>(0x90 | N)); 15826 } 15827 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15828 { 15829 // array 16 15830 oa->write_character(to_char_type(0xDC)); 15831 write_number(static_cast<std::uint16_t>(N)); 15832 } 15833 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15834 { 15835 // array 32 15836 oa->write_character(to_char_type(0xDD)); 15837 write_number(static_cast<std::uint32_t>(N)); 15838 } 15839 15840 // step 2: write each element 15841 for (const auto& el : *j.m_data.m_value.array) 15842 { 15843 write_msgpack(el); 15844 } 15845 break; 15846 } 15847 15848 case value_t::binary: 15849 { 15850 // step 0: determine if the binary type has a set subtype to 15851 // determine whether to use the ext or fixext types 15852 const bool use_ext = j.m_data.m_value.binary->has_subtype(); 15853 15854 // step 1: write control byte and the byte string length 15855 const auto N = j.m_data.m_value.binary->size(); 15856 if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15857 { 15858 std::uint8_t output_type{}; 15859 bool fixed = true; 15860 if (use_ext) 15861 { 15862 switch (N) 15863 { 15864 case 1: 15865 output_type = 0xD4; // fixext 1 15866 break; 15867 case 2: 15868 output_type = 0xD5; // fixext 2 15869 break; 15870 case 4: 15871 output_type = 0xD6; // fixext 4 15872 break; 15873 case 8: 15874 output_type = 0xD7; // fixext 8 15875 break; 15876 case 16: 15877 output_type = 0xD8; // fixext 16 15878 break; 15879 default: 15880 output_type = 0xC7; // ext 8 15881 fixed = false; 15882 break; 15883 } 15884 15885 } 15886 else 15887 { 15888 output_type = 0xC4; // bin 8 15889 fixed = false; 15890 } 15891 15892 oa->write_character(to_char_type(output_type)); 15893 if (!fixed) 15894 { 15895 write_number(static_cast<std::uint8_t>(N)); 15896 } 15897 } 15898 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15899 { 15900 const std::uint8_t output_type = use_ext 15901 ? 0xC8 // ext 16 15902 : 0xC5; // bin 16 15903 15904 oa->write_character(to_char_type(output_type)); 15905 write_number(static_cast<std::uint16_t>(N)); 15906 } 15907 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15908 { 15909 const std::uint8_t output_type = use_ext 15910 ? 0xC9 // ext 32 15911 : 0xC6; // bin 32 15912 15913 oa->write_character(to_char_type(output_type)); 15914 write_number(static_cast<std::uint32_t>(N)); 15915 } 15916 15917 // step 1.5: if this is an ext type, write the subtype 15918 if (use_ext) 15919 { 15920 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype())); 15921 } 15922 15923 // step 2: write the byte string 15924 oa->write_characters( 15925 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()), 15926 N); 15927 15928 break; 15929 } 15930 15931 case value_t::object: 15932 { 15933 // step 1: write control byte and the object size 15934 const auto N = j.m_data.m_value.object->size(); 15935 if (N <= 15) 15936 { 15937 // fixmap 15938 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF))); 15939 } 15940 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15941 { 15942 // map 16 15943 oa->write_character(to_char_type(0xDE)); 15944 write_number(static_cast<std::uint16_t>(N)); 15945 } 15946 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15947 { 15948 // map 32 15949 oa->write_character(to_char_type(0xDF)); 15950 write_number(static_cast<std::uint32_t>(N)); 15951 } 15952 15953 // step 2: write each element 15954 for (const auto& el : *j.m_data.m_value.object) 15955 { 15956 write_msgpack(el.first); 15957 write_msgpack(el.second); 15958 } 15959 break; 15960 } 15961 15962 case value_t::discarded: 15963 default: 15964 break; 15965 } 15966 } 15967 15968 /*! 15969 @param[in] j JSON value to serialize 15970 @param[in] use_count whether to use '#' prefixes (optimized format) 15971 @param[in] use_type whether to use '$' prefixes (optimized format) 15972 @param[in] add_prefix whether prefixes need to be used for this value 15973 @param[in] use_bjdata whether write in BJData format, default is false 15974 */ 15975 void write_ubjson(const BasicJsonType& j, const bool use_count, 15976 const bool use_type, const bool add_prefix = true, 15977 const bool use_bjdata = false) 15978 { 15979 switch (j.type()) 15980 { 15981 case value_t::null: 15982 { 15983 if (add_prefix) 15984 { 15985 oa->write_character(to_char_type('Z')); 15986 } 15987 break; 15988 } 15989 15990 case value_t::boolean: 15991 { 15992 if (add_prefix) 15993 { 15994 oa->write_character(j.m_data.m_value.boolean 15995 ? to_char_type('T') 15996 : to_char_type('F')); 15997 } 15998 break; 15999 } 16000 16001 case value_t::number_integer: 16002 { 16003 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata); 16004 break; 16005 } 16006 16007 case value_t::number_unsigned: 16008 { 16009 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata); 16010 break; 16011 } 16012 16013 case value_t::number_float: 16014 { 16015 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata); 16016 break; 16017 } 16018 16019 case value_t::string: 16020 { 16021 if (add_prefix) 16022 { 16023 oa->write_character(to_char_type('S')); 16024 } 16025 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata); 16026 oa->write_characters( 16027 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()), 16028 j.m_data.m_value.string->size()); 16029 break; 16030 } 16031 16032 case value_t::array: 16033 { 16034 if (add_prefix) 16035 { 16036 oa->write_character(to_char_type('[')); 16037 } 16038 16039 bool prefix_required = true; 16040 if (use_type && !j.m_data.m_value.array->empty()) 16041 { 16042 JSON_ASSERT(use_count); 16043 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata); 16044 const bool same_prefix = std::all_of(j.begin() + 1, j.end(), 16045 [this, first_prefix, use_bjdata](const BasicJsonType & v) 16046 { 16047 return ubjson_prefix(v, use_bjdata) == first_prefix; 16048 }); 16049 16050 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type 16051 16052 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end())) 16053 { 16054 prefix_required = false; 16055 oa->write_character(to_char_type('$')); 16056 oa->write_character(first_prefix); 16057 } 16058 } 16059 16060 if (use_count) 16061 { 16062 oa->write_character(to_char_type('#')); 16063 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata); 16064 } 16065 16066 for (const auto& el : *j.m_data.m_value.array) 16067 { 16068 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata); 16069 } 16070 16071 if (!use_count) 16072 { 16073 oa->write_character(to_char_type(']')); 16074 } 16075 16076 break; 16077 } 16078 16079 case value_t::binary: 16080 { 16081 if (add_prefix) 16082 { 16083 oa->write_character(to_char_type('[')); 16084 } 16085 16086 if (use_type && !j.m_data.m_value.binary->empty()) 16087 { 16088 JSON_ASSERT(use_count); 16089 oa->write_character(to_char_type('$')); 16090 oa->write_character('U'); 16091 } 16092 16093 if (use_count) 16094 { 16095 oa->write_character(to_char_type('#')); 16096 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata); 16097 } 16098 16099 if (use_type) 16100 { 16101 oa->write_characters( 16102 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()), 16103 j.m_data.m_value.binary->size()); 16104 } 16105 else 16106 { 16107 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i) 16108 { 16109 oa->write_character(to_char_type('U')); 16110 oa->write_character(j.m_data.m_value.binary->data()[i]); 16111 } 16112 } 16113 16114 if (!use_count) 16115 { 16116 oa->write_character(to_char_type(']')); 16117 } 16118 16119 break; 16120 } 16121 16122 case value_t::object: 16123 { 16124 if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end()) 16125 { 16126 if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata) 16127 { 16128 break; 16129 } 16130 } 16131 16132 if (add_prefix) 16133 { 16134 oa->write_character(to_char_type('{')); 16135 } 16136 16137 bool prefix_required = true; 16138 if (use_type && !j.m_data.m_value.object->empty()) 16139 { 16140 JSON_ASSERT(use_count); 16141 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata); 16142 const bool same_prefix = std::all_of(j.begin(), j.end(), 16143 [this, first_prefix, use_bjdata](const BasicJsonType & v) 16144 { 16145 return ubjson_prefix(v, use_bjdata) == first_prefix; 16146 }); 16147 16148 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type 16149 16150 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end())) 16151 { 16152 prefix_required = false; 16153 oa->write_character(to_char_type('$')); 16154 oa->write_character(first_prefix); 16155 } 16156 } 16157 16158 if (use_count) 16159 { 16160 oa->write_character(to_char_type('#')); 16161 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata); 16162 } 16163 16164 for (const auto& el : *j.m_data.m_value.object) 16165 { 16166 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata); 16167 oa->write_characters( 16168 reinterpret_cast<const CharType*>(el.first.c_str()), 16169 el.first.size()); 16170 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata); 16171 } 16172 16173 if (!use_count) 16174 { 16175 oa->write_character(to_char_type('}')); 16176 } 16177 16178 break; 16179 } 16180 16181 case value_t::discarded: 16182 default: 16183 break; 16184 } 16185 } 16186 16187 private: 16188 ////////// 16189 // BSON // 16190 ////////// 16191 16192 /*! 16193 @return The size of a BSON document entry header, including the id marker 16194 and the entry name size (and its null-terminator). 16195 */ 16196 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j) 16197 { 16198 const auto it = name.find(static_cast<typename string_t::value_type>(0)); 16199 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) 16200 { 16201 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j)); 16202 static_cast<void>(j); 16203 } 16204 16205 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; 16206 } 16207 16208 /*! 16209 @brief Writes the given @a element_type and @a name to the output adapter 16210 */ 16211 void write_bson_entry_header(const string_t& name, 16212 const std::uint8_t element_type) 16213 { 16214 oa->write_character(to_char_type(element_type)); // boolean 16215 oa->write_characters( 16216 reinterpret_cast<const CharType*>(name.c_str()), 16217 name.size() + 1u); 16218 } 16219 16220 /*! 16221 @brief Writes a BSON element with key @a name and boolean value @a value 16222 */ 16223 void write_bson_boolean(const string_t& name, 16224 const bool value) 16225 { 16226 write_bson_entry_header(name, 0x08); 16227 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00)); 16228 } 16229 16230 /*! 16231 @brief Writes a BSON element with key @a name and double value @a value 16232 */ 16233 void write_bson_double(const string_t& name, 16234 const double value) 16235 { 16236 write_bson_entry_header(name, 0x01); 16237 write_number<double>(value, true); 16238 } 16239 16240 /*! 16241 @return The size of the BSON-encoded string in @a value 16242 */ 16243 static std::size_t calc_bson_string_size(const string_t& value) 16244 { 16245 return sizeof(std::int32_t) + value.size() + 1ul; 16246 } 16247 16248 /*! 16249 @brief Writes a BSON element with key @a name and string value @a value 16250 */ 16251 void write_bson_string(const string_t& name, 16252 const string_t& value) 16253 { 16254 write_bson_entry_header(name, 0x02); 16255 16256 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true); 16257 oa->write_characters( 16258 reinterpret_cast<const CharType*>(value.c_str()), 16259 value.size() + 1); 16260 } 16261 16262 /*! 16263 @brief Writes a BSON element with key @a name and null value 16264 */ 16265 void write_bson_null(const string_t& name) 16266 { 16267 write_bson_entry_header(name, 0x0A); 16268 } 16269 16270 /*! 16271 @return The size of the BSON-encoded integer @a value 16272 */ 16273 static std::size_t calc_bson_integer_size(const std::int64_t value) 16274 { 16275 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)() 16276 ? sizeof(std::int32_t) 16277 : sizeof(std::int64_t); 16278 } 16279 16280 /*! 16281 @brief Writes a BSON element with key @a name and integer @a value 16282 */ 16283 void write_bson_integer(const string_t& name, 16284 const std::int64_t value) 16285 { 16286 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()) 16287 { 16288 write_bson_entry_header(name, 0x10); // int32 16289 write_number<std::int32_t>(static_cast<std::int32_t>(value), true); 16290 } 16291 else 16292 { 16293 write_bson_entry_header(name, 0x12); // int64 16294 write_number<std::int64_t>(static_cast<std::int64_t>(value), true); 16295 } 16296 } 16297 16298 /*! 16299 @return The size of the BSON-encoded unsigned integer in @a j 16300 */ 16301 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept 16302 { 16303 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) 16304 ? sizeof(std::int32_t) 16305 : sizeof(std::int64_t); 16306 } 16307 16308 /*! 16309 @brief Writes a BSON element with key @a name and unsigned @a value 16310 */ 16311 void write_bson_unsigned(const string_t& name, 16312 const BasicJsonType& j) 16313 { 16314 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) 16315 { 16316 write_bson_entry_header(name, 0x10 /* int32 */); 16317 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true); 16318 } 16319 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) 16320 { 16321 write_bson_entry_header(name, 0x12 /* int64 */); 16322 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true); 16323 } 16324 else 16325 { 16326 JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j)); 16327 } 16328 } 16329 16330 /*! 16331 @brief Writes a BSON element with key @a name and object @a value 16332 */ 16333 void write_bson_object_entry(const string_t& name, 16334 const typename BasicJsonType::object_t& value) 16335 { 16336 write_bson_entry_header(name, 0x03); // object 16337 write_bson_object(value); 16338 } 16339 16340 /*! 16341 @return The size of the BSON-encoded array @a value 16342 */ 16343 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value) 16344 { 16345 std::size_t array_index = 0ul; 16346 16347 const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el) 16348 { 16349 return result + calc_bson_element_size(std::to_string(array_index++), el); 16350 }); 16351 16352 return sizeof(std::int32_t) + embedded_document_size + 1ul; 16353 } 16354 16355 /*! 16356 @return The size of the BSON-encoded binary array @a value 16357 */ 16358 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value) 16359 { 16360 return sizeof(std::int32_t) + value.size() + 1ul; 16361 } 16362 16363 /*! 16364 @brief Writes a BSON element with key @a name and array @a value 16365 */ 16366 void write_bson_array(const string_t& name, 16367 const typename BasicJsonType::array_t& value) 16368 { 16369 write_bson_entry_header(name, 0x04); // array 16370 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true); 16371 16372 std::size_t array_index = 0ul; 16373 16374 for (const auto& el : value) 16375 { 16376 write_bson_element(std::to_string(array_index++), el); 16377 } 16378 16379 oa->write_character(to_char_type(0x00)); 16380 } 16381 16382 /*! 16383 @brief Writes a BSON element with key @a name and binary value @a value 16384 */ 16385 void write_bson_binary(const string_t& name, 16386 const binary_t& value) 16387 { 16388 write_bson_entry_header(name, 0x05); 16389 16390 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true); 16391 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00)); 16392 16393 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size()); 16394 } 16395 16396 /*! 16397 @brief Calculates the size necessary to serialize the JSON value @a j with its @a name 16398 @return The calculated size for the BSON document entry for @a j with the given @a name. 16399 */ 16400 static std::size_t calc_bson_element_size(const string_t& name, 16401 const BasicJsonType& j) 16402 { 16403 const auto header_size = calc_bson_entry_header_size(name, j); 16404 switch (j.type()) 16405 { 16406 case value_t::object: 16407 return header_size + calc_bson_object_size(*j.m_data.m_value.object); 16408 16409 case value_t::array: 16410 return header_size + calc_bson_array_size(*j.m_data.m_value.array); 16411 16412 case value_t::binary: 16413 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary); 16414 16415 case value_t::boolean: 16416 return header_size + 1ul; 16417 16418 case value_t::number_float: 16419 return header_size + 8ul; 16420 16421 case value_t::number_integer: 16422 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer); 16423 16424 case value_t::number_unsigned: 16425 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned); 16426 16427 case value_t::string: 16428 return header_size + calc_bson_string_size(*j.m_data.m_value.string); 16429 16430 case value_t::null: 16431 return header_size + 0ul; 16432 16433 // LCOV_EXCL_START 16434 case value_t::discarded: 16435 default: 16436 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) 16437 return 0ul; 16438 // LCOV_EXCL_STOP 16439 } 16440 } 16441 16442 /*! 16443 @brief Serializes the JSON value @a j to BSON and associates it with the 16444 key @a name. 16445 @param name The name to associate with the JSON entity @a j within the 16446 current BSON document 16447 */ 16448 void write_bson_element(const string_t& name, 16449 const BasicJsonType& j) 16450 { 16451 switch (j.type()) 16452 { 16453 case value_t::object: 16454 return write_bson_object_entry(name, *j.m_data.m_value.object); 16455 16456 case value_t::array: 16457 return write_bson_array(name, *j.m_data.m_value.array); 16458 16459 case value_t::binary: 16460 return write_bson_binary(name, *j.m_data.m_value.binary); 16461 16462 case value_t::boolean: 16463 return write_bson_boolean(name, j.m_data.m_value.boolean); 16464 16465 case value_t::number_float: 16466 return write_bson_double(name, j.m_data.m_value.number_float); 16467 16468 case value_t::number_integer: 16469 return write_bson_integer(name, j.m_data.m_value.number_integer); 16470 16471 case value_t::number_unsigned: 16472 return write_bson_unsigned(name, j); 16473 16474 case value_t::string: 16475 return write_bson_string(name, *j.m_data.m_value.string); 16476 16477 case value_t::null: 16478 return write_bson_null(name); 16479 16480 // LCOV_EXCL_START 16481 case value_t::discarded: 16482 default: 16483 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) 16484 return; 16485 // LCOV_EXCL_STOP 16486 } 16487 } 16488 16489 /*! 16490 @brief Calculates the size of the BSON serialization of the given 16491 JSON-object @a j. 16492 @param[in] value JSON value to serialize 16493 @pre value.type() == value_t::object 16494 */ 16495 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) 16496 { 16497 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0), 16498 [](size_t result, const typename BasicJsonType::object_t::value_type & el) 16499 { 16500 return result += calc_bson_element_size(el.first, el.second); 16501 }); 16502 16503 return sizeof(std::int32_t) + document_size + 1ul; 16504 } 16505 16506 /*! 16507 @param[in] value JSON value to serialize 16508 @pre value.type() == value_t::object 16509 */ 16510 void write_bson_object(const typename BasicJsonType::object_t& value) 16511 { 16512 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true); 16513 16514 for (const auto& el : value) 16515 { 16516 write_bson_element(el.first, el.second); 16517 } 16518 16519 oa->write_character(to_char_type(0x00)); 16520 } 16521 16522 ////////// 16523 // CBOR // 16524 ////////// 16525 16526 static constexpr CharType get_cbor_float_prefix(float /*unused*/) 16527 { 16528 return to_char_type(0xFA); // Single-Precision Float 16529 } 16530 16531 static constexpr CharType get_cbor_float_prefix(double /*unused*/) 16532 { 16533 return to_char_type(0xFB); // Double-Precision Float 16534 } 16535 16536 ///////////// 16537 // MsgPack // 16538 ///////////// 16539 16540 static constexpr CharType get_msgpack_float_prefix(float /*unused*/) 16541 { 16542 return to_char_type(0xCA); // float 32 16543 } 16544 16545 static constexpr CharType get_msgpack_float_prefix(double /*unused*/) 16546 { 16547 return to_char_type(0xCB); // float 64 16548 } 16549 16550 //////////// 16551 // UBJSON // 16552 //////////// 16553 16554 // UBJSON: write number (floating point) 16555 template<typename NumberType, typename std::enable_if< 16556 std::is_floating_point<NumberType>::value, int>::type = 0> 16557 void write_number_with_ubjson_prefix(const NumberType n, 16558 const bool add_prefix, 16559 const bool use_bjdata) 16560 { 16561 if (add_prefix) 16562 { 16563 oa->write_character(get_ubjson_float_prefix(n)); 16564 } 16565 write_number(n, use_bjdata); 16566 } 16567 16568 // UBJSON: write number (unsigned integer) 16569 template<typename NumberType, typename std::enable_if< 16570 std::is_unsigned<NumberType>::value, int>::type = 0> 16571 void write_number_with_ubjson_prefix(const NumberType n, 16572 const bool add_prefix, 16573 const bool use_bjdata) 16574 { 16575 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)())) 16576 { 16577 if (add_prefix) 16578 { 16579 oa->write_character(to_char_type('i')); // int8 16580 } 16581 write_number(static_cast<std::uint8_t>(n), use_bjdata); 16582 } 16583 else if (n <= (std::numeric_limits<std::uint8_t>::max)()) 16584 { 16585 if (add_prefix) 16586 { 16587 oa->write_character(to_char_type('U')); // uint8 16588 } 16589 write_number(static_cast<std::uint8_t>(n), use_bjdata); 16590 } 16591 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)())) 16592 { 16593 if (add_prefix) 16594 { 16595 oa->write_character(to_char_type('I')); // int16 16596 } 16597 write_number(static_cast<std::int16_t>(n), use_bjdata); 16598 } 16599 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)())) 16600 { 16601 if (add_prefix) 16602 { 16603 oa->write_character(to_char_type('u')); // uint16 - bjdata only 16604 } 16605 write_number(static_cast<std::uint16_t>(n), use_bjdata); 16606 } 16607 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) 16608 { 16609 if (add_prefix) 16610 { 16611 oa->write_character(to_char_type('l')); // int32 16612 } 16613 write_number(static_cast<std::int32_t>(n), use_bjdata); 16614 } 16615 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)())) 16616 { 16617 if (add_prefix) 16618 { 16619 oa->write_character(to_char_type('m')); // uint32 - bjdata only 16620 } 16621 write_number(static_cast<std::uint32_t>(n), use_bjdata); 16622 } 16623 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) 16624 { 16625 if (add_prefix) 16626 { 16627 oa->write_character(to_char_type('L')); // int64 16628 } 16629 write_number(static_cast<std::int64_t>(n), use_bjdata); 16630 } 16631 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)()) 16632 { 16633 if (add_prefix) 16634 { 16635 oa->write_character(to_char_type('M')); // uint64 - bjdata only 16636 } 16637 write_number(static_cast<std::uint64_t>(n), use_bjdata); 16638 } 16639 else 16640 { 16641 if (add_prefix) 16642 { 16643 oa->write_character(to_char_type('H')); // high-precision number 16644 } 16645 16646 const auto number = BasicJsonType(n).dump(); 16647 write_number_with_ubjson_prefix(number.size(), true, use_bjdata); 16648 for (std::size_t i = 0; i < number.size(); ++i) 16649 { 16650 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i]))); 16651 } 16652 } 16653 } 16654 16655 // UBJSON: write number (signed integer) 16656 template < typename NumberType, typename std::enable_if < 16657 std::is_signed<NumberType>::value&& 16658 !std::is_floating_point<NumberType>::value, int >::type = 0 > 16659 void write_number_with_ubjson_prefix(const NumberType n, 16660 const bool add_prefix, 16661 const bool use_bjdata) 16662 { 16663 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)()) 16664 { 16665 if (add_prefix) 16666 { 16667 oa->write_character(to_char_type('i')); // int8 16668 } 16669 write_number(static_cast<std::int8_t>(n), use_bjdata); 16670 } 16671 else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)())) 16672 { 16673 if (add_prefix) 16674 { 16675 oa->write_character(to_char_type('U')); // uint8 16676 } 16677 write_number(static_cast<std::uint8_t>(n), use_bjdata); 16678 } 16679 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)()) 16680 { 16681 if (add_prefix) 16682 { 16683 oa->write_character(to_char_type('I')); // int16 16684 } 16685 write_number(static_cast<std::int16_t>(n), use_bjdata); 16686 } 16687 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)()))) 16688 { 16689 if (add_prefix) 16690 { 16691 oa->write_character(to_char_type('u')); // uint16 - bjdata only 16692 } 16693 write_number(static_cast<uint16_t>(n), use_bjdata); 16694 } 16695 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)()) 16696 { 16697 if (add_prefix) 16698 { 16699 oa->write_character(to_char_type('l')); // int32 16700 } 16701 write_number(static_cast<std::int32_t>(n), use_bjdata); 16702 } 16703 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)()))) 16704 { 16705 if (add_prefix) 16706 { 16707 oa->write_character(to_char_type('m')); // uint32 - bjdata only 16708 } 16709 write_number(static_cast<uint32_t>(n), use_bjdata); 16710 } 16711 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)()) 16712 { 16713 if (add_prefix) 16714 { 16715 oa->write_character(to_char_type('L')); // int64 16716 } 16717 write_number(static_cast<std::int64_t>(n), use_bjdata); 16718 } 16719 // LCOV_EXCL_START 16720 else 16721 { 16722 if (add_prefix) 16723 { 16724 oa->write_character(to_char_type('H')); // high-precision number 16725 } 16726 16727 const auto number = BasicJsonType(n).dump(); 16728 write_number_with_ubjson_prefix(number.size(), true, use_bjdata); 16729 for (std::size_t i = 0; i < number.size(); ++i) 16730 { 16731 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i]))); 16732 } 16733 } 16734 // LCOV_EXCL_STOP 16735 } 16736 16737 /*! 16738 @brief determine the type prefix of container values 16739 */ 16740 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept 16741 { 16742 switch (j.type()) 16743 { 16744 case value_t::null: 16745 return 'Z'; 16746 16747 case value_t::boolean: 16748 return j.m_data.m_value.boolean ? 'T' : 'F'; 16749 16750 case value_t::number_integer: 16751 { 16752 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)()) 16753 { 16754 return 'i'; 16755 } 16756 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)()) 16757 { 16758 return 'U'; 16759 } 16760 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)()) 16761 { 16762 return 'I'; 16763 } 16764 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())) 16765 { 16766 return 'u'; 16767 } 16768 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)()) 16769 { 16770 return 'l'; 16771 } 16772 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())) 16773 { 16774 return 'm'; 16775 } 16776 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)()) 16777 { 16778 return 'L'; 16779 } 16780 // anything else is treated as high-precision number 16781 return 'H'; // LCOV_EXCL_LINE 16782 } 16783 16784 case value_t::number_unsigned: 16785 { 16786 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)())) 16787 { 16788 return 'i'; 16789 } 16790 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)())) 16791 { 16792 return 'U'; 16793 } 16794 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)())) 16795 { 16796 return 'I'; 16797 } 16798 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)())) 16799 { 16800 return 'u'; 16801 } 16802 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) 16803 { 16804 return 'l'; 16805 } 16806 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)())) 16807 { 16808 return 'm'; 16809 } 16810 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) 16811 { 16812 return 'L'; 16813 } 16814 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) 16815 { 16816 return 'M'; 16817 } 16818 // anything else is treated as high-precision number 16819 return 'H'; // LCOV_EXCL_LINE 16820 } 16821 16822 case value_t::number_float: 16823 return get_ubjson_float_prefix(j.m_data.m_value.number_float); 16824 16825 case value_t::string: 16826 return 'S'; 16827 16828 case value_t::array: // fallthrough 16829 case value_t::binary: 16830 return '['; 16831 16832 case value_t::object: 16833 return '{'; 16834 16835 case value_t::discarded: 16836 default: // discarded values 16837 return 'N'; 16838 } 16839 } 16840 16841 static constexpr CharType get_ubjson_float_prefix(float /*unused*/) 16842 { 16843 return 'd'; // float 32 16844 } 16845 16846 static constexpr CharType get_ubjson_float_prefix(double /*unused*/) 16847 { 16848 return 'D'; // float 64 16849 } 16850 16851 /*! 16852 @return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid 16853 */ 16854 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type) 16855 { 16856 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'}, 16857 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'} 16858 }; 16859 16860 string_t key = "_ArrayType_"; 16861 auto it = bjdtype.find(static_cast<string_t>(value.at(key))); 16862 if (it == bjdtype.end()) 16863 { 16864 return true; 16865 } 16866 CharType dtype = it->second; 16867 16868 key = "_ArraySize_"; 16869 std::size_t len = (value.at(key).empty() ? 0 : 1); 16870 for (const auto& el : value.at(key)) 16871 { 16872 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned); 16873 } 16874 16875 key = "_ArrayData_"; 16876 if (value.at(key).size() != len) 16877 { 16878 return true; 16879 } 16880 16881 oa->write_character('['); 16882 oa->write_character('$'); 16883 oa->write_character(dtype); 16884 oa->write_character('#'); 16885 16886 key = "_ArraySize_"; 16887 write_ubjson(value.at(key), use_count, use_type, true, true); 16888 16889 key = "_ArrayData_"; 16890 if (dtype == 'U' || dtype == 'C') 16891 { 16892 for (const auto& el : value.at(key)) 16893 { 16894 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true); 16895 } 16896 } 16897 else if (dtype == 'i') 16898 { 16899 for (const auto& el : value.at(key)) 16900 { 16901 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true); 16902 } 16903 } 16904 else if (dtype == 'u') 16905 { 16906 for (const auto& el : value.at(key)) 16907 { 16908 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true); 16909 } 16910 } 16911 else if (dtype == 'I') 16912 { 16913 for (const auto& el : value.at(key)) 16914 { 16915 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true); 16916 } 16917 } 16918 else if (dtype == 'm') 16919 { 16920 for (const auto& el : value.at(key)) 16921 { 16922 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true); 16923 } 16924 } 16925 else if (dtype == 'l') 16926 { 16927 for (const auto& el : value.at(key)) 16928 { 16929 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true); 16930 } 16931 } 16932 else if (dtype == 'M') 16933 { 16934 for (const auto& el : value.at(key)) 16935 { 16936 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true); 16937 } 16938 } 16939 else if (dtype == 'L') 16940 { 16941 for (const auto& el : value.at(key)) 16942 { 16943 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true); 16944 } 16945 } 16946 else if (dtype == 'd') 16947 { 16948 for (const auto& el : value.at(key)) 16949 { 16950 write_number(static_cast<float>(el.m_data.m_value.number_float), true); 16951 } 16952 } 16953 else if (dtype == 'D') 16954 { 16955 for (const auto& el : value.at(key)) 16956 { 16957 write_number(static_cast<double>(el.m_data.m_value.number_float), true); 16958 } 16959 } 16960 return false; 16961 } 16962 16963 /////////////////////// 16964 // Utility functions // 16965 /////////////////////// 16966 16967 /* 16968 @brief write a number to output input 16969 @param[in] n number of type @a NumberType 16970 @param[in] OutputIsLittleEndian Set to true if output data is 16971 required to be little endian 16972 @tparam NumberType the type of the number 16973 16974 @note This function needs to respect the system's endianness, because bytes 16975 in CBOR, MessagePack, and UBJSON are stored in network order (big 16976 endian) and therefore need reordering on little endian systems. 16977 On the other hand, BSON and BJData use little endian and should reorder 16978 on big endian systems. 16979 */ 16980 template<typename NumberType> 16981 void write_number(const NumberType n, const bool OutputIsLittleEndian = false) 16982 { 16983 // step 1: write number to array of length NumberType 16984 std::array<CharType, sizeof(NumberType)> vec{}; 16985 std::memcpy(vec.data(), &n, sizeof(NumberType)); 16986 16987 // step 2: write array to output (with possible reordering) 16988 if (is_little_endian != OutputIsLittleEndian) 16989 { 16990 // reverse byte order prior to conversion if necessary 16991 std::reverse(vec.begin(), vec.end()); 16992 } 16993 16994 oa->write_characters(vec.data(), sizeof(NumberType)); 16995 } 16996 16997 void write_compact_float(const number_float_t n, detail::input_format_t format) 16998 { 16999 #ifdef __GNUC__ 17000 #pragma GCC diagnostic push 17001 #pragma GCC diagnostic ignored "-Wfloat-equal" 17002 #endif 17003 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) && 17004 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) && 17005 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n)) 17006 { 17007 oa->write_character(format == detail::input_format_t::cbor 17008 ? get_cbor_float_prefix(static_cast<float>(n)) 17009 : get_msgpack_float_prefix(static_cast<float>(n))); 17010 write_number(static_cast<float>(n)); 17011 } 17012 else 17013 { 17014 oa->write_character(format == detail::input_format_t::cbor 17015 ? get_cbor_float_prefix(n) 17016 : get_msgpack_float_prefix(n)); 17017 write_number(n); 17018 } 17019 #ifdef __GNUC__ 17020 #pragma GCC diagnostic pop 17021 #endif 17022 } 17023 17024 public: 17025 // The following to_char_type functions are implement the conversion 17026 // between uint8_t and CharType. In case CharType is not unsigned, 17027 // such a conversion is required to allow values greater than 128. 17028 // See <https://github.com/nlohmann/json/issues/1286> for a discussion. 17029 template < typename C = CharType, 17030 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr > 17031 static constexpr CharType to_char_type(std::uint8_t x) noexcept 17032 { 17033 return *reinterpret_cast<char*>(&x); 17034 } 17035 17036 template < typename C = CharType, 17037 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr > 17038 static CharType to_char_type(std::uint8_t x) noexcept 17039 { 17040 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t"); 17041 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial"); 17042 CharType result; 17043 std::memcpy(&result, &x, sizeof(x)); 17044 return result; 17045 } 17046 17047 template<typename C = CharType, 17048 enable_if_t<std::is_unsigned<C>::value>* = nullptr> 17049 static constexpr CharType to_char_type(std::uint8_t x) noexcept 17050 { 17051 return x; 17052 } 17053 17054 template < typename InputCharType, typename C = CharType, 17055 enable_if_t < 17056 std::is_signed<C>::value && 17057 std::is_signed<char>::value && 17058 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value 17059 > * = nullptr > 17060 static constexpr CharType to_char_type(InputCharType x) noexcept 17061 { 17062 return x; 17063 } 17064 17065 private: 17066 /// whether we can assume little endianness 17067 const bool is_little_endian = little_endianness(); 17068 17069 /// the output 17070 output_adapter_t<CharType> oa = nullptr; 17071 }; 17072 17073 } // namespace detail 17074 NLOHMANN_JSON_NAMESPACE_END 17075 17076 // #include <nlohmann/detail/output/output_adapters.hpp> 17077 17078 // #include <nlohmann/detail/output/serializer.hpp> 17079 // __ _____ _____ _____ 17080 // __| | __| | | | JSON for Modern C++ 17081 // | | |__ | | | | | | version 3.11.3 17082 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 17083 // 17084 // SPDX-FileCopyrightText: 2008 - 2009 Björn Hoehrmann <bjoern@hoehrmann.de> 17085 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 17086 // SPDX-License-Identifier: MIT 17087 17088 17089 17090 #include <algorithm> // reverse, remove, fill, find, none_of 17091 #include <array> // array 17092 #include <clocale> // localeconv, lconv 17093 #include <cmath> // labs, isfinite, isnan, signbit 17094 #include <cstddef> // size_t, ptrdiff_t 17095 #include <cstdint> // uint8_t 17096 #include <cstdio> // snprintf 17097 #include <limits> // numeric_limits 17098 #include <string> // string, char_traits 17099 #include <iomanip> // setfill, setw 17100 #include <type_traits> // is_same 17101 #include <utility> // move 17102 17103 // #include <nlohmann/detail/conversions/to_chars.hpp> 17104 // __ _____ _____ _____ 17105 // __| | __| | | | JSON for Modern C++ 17106 // | | |__ | | | | | | version 3.11.3 17107 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 17108 // 17109 // SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/> 17110 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 17111 // SPDX-License-Identifier: MIT 17112 17113 17114 17115 #include <array> // array 17116 #include <cmath> // signbit, isfinite 17117 #include <cstdint> // intN_t, uintN_t 17118 #include <cstring> // memcpy, memmove 17119 #include <limits> // numeric_limits 17120 #include <type_traits> // conditional 17121 17122 // #include <nlohmann/detail/macro_scope.hpp> 17123 17124 17125 NLOHMANN_JSON_NAMESPACE_BEGIN 17126 namespace detail 17127 { 17128 17129 /*! 17130 @brief implements the Grisu2 algorithm for binary to decimal floating-point 17131 conversion. 17132 17133 This implementation is a slightly modified version of the reference 17134 implementation which may be obtained from 17135 http://florian.loitsch.com/publications (bench.tar.gz). 17136 17137 The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch. 17138 17139 For a detailed description of the algorithm see: 17140 17141 [1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with 17142 Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming 17143 Language Design and Implementation, PLDI 2010 17144 [2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", 17145 Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language 17146 Design and Implementation, PLDI 1996 17147 */ 17148 namespace dtoa_impl 17149 { 17150 17151 template<typename Target, typename Source> 17152 Target reinterpret_bits(const Source source) 17153 { 17154 static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); 17155 17156 Target target; 17157 std::memcpy(&target, &source, sizeof(Source)); 17158 return target; 17159 } 17160 17161 struct diyfp // f * 2^e 17162 { 17163 static constexpr int kPrecision = 64; // = q 17164 17165 std::uint64_t f = 0; 17166 int e = 0; 17167 17168 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {} 17169 17170 /*! 17171 @brief returns x - y 17172 @pre x.e == y.e and x.f >= y.f 17173 */ 17174 static diyfp sub(const diyfp& x, const diyfp& y) noexcept 17175 { 17176 JSON_ASSERT(x.e == y.e); 17177 JSON_ASSERT(x.f >= y.f); 17178 17179 return {x.f - y.f, x.e}; 17180 } 17181 17182 /*! 17183 @brief returns x * y 17184 @note The result is rounded. (Only the upper q bits are returned.) 17185 */ 17186 static diyfp mul(const diyfp& x, const diyfp& y) noexcept 17187 { 17188 static_assert(kPrecision == 64, "internal error"); 17189 17190 // Computes: 17191 // f = round((x.f * y.f) / 2^q) 17192 // e = x.e + y.e + q 17193 17194 // Emulate the 64-bit * 64-bit multiplication: 17195 // 17196 // p = u * v 17197 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) 17198 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) 17199 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) 17200 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) 17201 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) 17202 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) 17203 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) 17204 // 17205 // (Since Q might be larger than 2^32 - 1) 17206 // 17207 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) 17208 // 17209 // (Q_hi + H does not overflow a 64-bit int) 17210 // 17211 // = p_lo + 2^64 p_hi 17212 17213 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; 17214 const std::uint64_t u_hi = x.f >> 32u; 17215 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; 17216 const std::uint64_t v_hi = y.f >> 32u; 17217 17218 const std::uint64_t p0 = u_lo * v_lo; 17219 const std::uint64_t p1 = u_lo * v_hi; 17220 const std::uint64_t p2 = u_hi * v_lo; 17221 const std::uint64_t p3 = u_hi * v_hi; 17222 17223 const std::uint64_t p0_hi = p0 >> 32u; 17224 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; 17225 const std::uint64_t p1_hi = p1 >> 32u; 17226 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; 17227 const std::uint64_t p2_hi = p2 >> 32u; 17228 17229 std::uint64_t Q = p0_hi + p1_lo + p2_lo; 17230 17231 // The full product might now be computed as 17232 // 17233 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) 17234 // p_lo = p0_lo + (Q << 32) 17235 // 17236 // But in this particular case here, the full p_lo is not required. 17237 // Effectively we only need to add the highest bit in p_lo to p_hi (and 17238 // Q_hi + 1 does not overflow). 17239 17240 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up 17241 17242 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); 17243 17244 return {h, x.e + y.e + 64}; 17245 } 17246 17247 /*! 17248 @brief normalize x such that the significand is >= 2^(q-1) 17249 @pre x.f != 0 17250 */ 17251 static diyfp normalize(diyfp x) noexcept 17252 { 17253 JSON_ASSERT(x.f != 0); 17254 17255 while ((x.f >> 63u) == 0) 17256 { 17257 x.f <<= 1u; 17258 x.e--; 17259 } 17260 17261 return x; 17262 } 17263 17264 /*! 17265 @brief normalize x such that the result has the exponent E 17266 @pre e >= x.e and the upper e - x.e bits of x.f must be zero. 17267 */ 17268 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept 17269 { 17270 const int delta = x.e - target_exponent; 17271 17272 JSON_ASSERT(delta >= 0); 17273 JSON_ASSERT(((x.f << delta) >> delta) == x.f); 17274 17275 return {x.f << delta, target_exponent}; 17276 } 17277 }; 17278 17279 struct boundaries 17280 { 17281 diyfp w; 17282 diyfp minus; 17283 diyfp plus; 17284 }; 17285 17286 /*! 17287 Compute the (normalized) diyfp representing the input number 'value' and its 17288 boundaries. 17289 17290 @pre value must be finite and positive 17291 */ 17292 template<typename FloatType> 17293 boundaries compute_boundaries(FloatType value) 17294 { 17295 JSON_ASSERT(std::isfinite(value)); 17296 JSON_ASSERT(value > 0); 17297 17298 // Convert the IEEE representation into a diyfp. 17299 // 17300 // If v is denormal: 17301 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) 17302 // If v is normalized: 17303 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) 17304 17305 static_assert(std::numeric_limits<FloatType>::is_iec559, 17306 "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); 17307 17308 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit) 17309 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1); 17310 constexpr int kMinExp = 1 - kBias; 17311 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1) 17312 17313 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type; 17314 17315 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value)); 17316 const std::uint64_t E = bits >> (kPrecision - 1); 17317 const std::uint64_t F = bits & (kHiddenBit - 1); 17318 17319 const bool is_denormal = E == 0; 17320 const diyfp v = is_denormal 17321 ? diyfp(F, kMinExp) 17322 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias); 17323 17324 // Compute the boundaries m- and m+ of the floating-point value 17325 // v = f * 2^e. 17326 // 17327 // Determine v- and v+, the floating-point predecessor and successor if v, 17328 // respectively. 17329 // 17330 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) 17331 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) 17332 // 17333 // v+ = v + 2^e 17334 // 17335 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ 17336 // between m- and m+ round to v, regardless of how the input rounding 17337 // algorithm breaks ties. 17338 // 17339 // ---+-------------+-------------+-------------+-------------+--- (A) 17340 // v- m- v m+ v+ 17341 // 17342 // -----------------+------+------+-------------+-------------+--- (B) 17343 // v- m- v m+ v+ 17344 17345 const bool lower_boundary_is_closer = F == 0 && E > 1; 17346 const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1); 17347 const diyfp m_minus = lower_boundary_is_closer 17348 ? diyfp((4 * v.f) - 1, v.e - 2) // (B) 17349 : diyfp((2 * v.f) - 1, v.e - 1); // (A) 17350 17351 // Determine the normalized w+ = m+. 17352 const diyfp w_plus = diyfp::normalize(m_plus); 17353 17354 // Determine w- = m- such that e_(w-) = e_(w+). 17355 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); 17356 17357 return {diyfp::normalize(v), w_minus, w_plus}; 17358 } 17359 17360 // Given normalized diyfp w, Grisu needs to find a (normalized) cached 17361 // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies 17362 // within a certain range [alpha, gamma] (Definition 3.2 from [1]) 17363 // 17364 // alpha <= e = e_c + e_w + q <= gamma 17365 // 17366 // or 17367 // 17368 // f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q 17369 // <= f_c * f_w * 2^gamma 17370 // 17371 // Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies 17372 // 17373 // 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma 17374 // 17375 // or 17376 // 17377 // 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) 17378 // 17379 // The choice of (alpha,gamma) determines the size of the table and the form of 17380 // the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well 17381 // in practice: 17382 // 17383 // The idea is to cut the number c * w = f * 2^e into two parts, which can be 17384 // processed independently: An integral part p1, and a fractional part p2: 17385 // 17386 // f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e 17387 // = (f div 2^-e) + (f mod 2^-e) * 2^e 17388 // = p1 + p2 * 2^e 17389 // 17390 // The conversion of p1 into decimal form requires a series of divisions and 17391 // modulos by (a power of) 10. These operations are faster for 32-bit than for 17392 // 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be 17393 // achieved by choosing 17394 // 17395 // -e >= 32 or e <= -32 := gamma 17396 // 17397 // In order to convert the fractional part 17398 // 17399 // p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... 17400 // 17401 // into decimal form, the fraction is repeatedly multiplied by 10 and the digits 17402 // d[-i] are extracted in order: 17403 // 17404 // (10 * p2) div 2^-e = d[-1] 17405 // (10 * p2) mod 2^-e = d[-2] / 10^1 + ... 17406 // 17407 // The multiplication by 10 must not overflow. It is sufficient to choose 17408 // 17409 // 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. 17410 // 17411 // Since p2 = f mod 2^-e < 2^-e, 17412 // 17413 // -e <= 60 or e >= -60 := alpha 17414 17415 constexpr int kAlpha = -60; 17416 constexpr int kGamma = -32; 17417 17418 struct cached_power // c = f * 2^e ~= 10^k 17419 { 17420 std::uint64_t f; 17421 int e; 17422 int k; 17423 }; 17424 17425 /*! 17426 For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached 17427 power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c 17428 satisfies (Definition 3.2 from [1]) 17429 17430 alpha <= e_c + e + q <= gamma. 17431 */ 17432 inline cached_power get_cached_power_for_binary_exponent(int e) 17433 { 17434 // Now 17435 // 17436 // alpha <= e_c + e + q <= gamma (1) 17437 // ==> f_c * 2^alpha <= c * 2^e * 2^q 17438 // 17439 // and since the c's are normalized, 2^(q-1) <= f_c, 17440 // 17441 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) 17442 // ==> 2^(alpha - e - 1) <= c 17443 // 17444 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as 17445 // 17446 // k = ceil( log_10( 2^(alpha - e - 1) ) ) 17447 // = ceil( (alpha - e - 1) * log_10(2) ) 17448 // 17449 // From the paper: 17450 // "In theory the result of the procedure could be wrong since c is rounded, 17451 // and the computation itself is approximated [...]. In practice, however, 17452 // this simple function is sufficient." 17453 // 17454 // For IEEE double precision floating-point numbers converted into 17455 // normalized diyfp's w = f * 2^e, with q = 64, 17456 // 17457 // e >= -1022 (min IEEE exponent) 17458 // -52 (p - 1) 17459 // -52 (p - 1, possibly normalize denormal IEEE numbers) 17460 // -11 (normalize the diyfp) 17461 // = -1137 17462 // 17463 // and 17464 // 17465 // e <= +1023 (max IEEE exponent) 17466 // -52 (p - 1) 17467 // -11 (normalize the diyfp) 17468 // = 960 17469 // 17470 // This binary exponent range [-1137,960] results in a decimal exponent 17471 // range [-307,324]. One does not need to store a cached power for each 17472 // k in this range. For each such k it suffices to find a cached power 17473 // such that the exponent of the product lies in [alpha,gamma]. 17474 // This implies that the difference of the decimal exponents of adjacent 17475 // table entries must be less than or equal to 17476 // 17477 // floor( (gamma - alpha) * log_10(2) ) = 8. 17478 // 17479 // (A smaller distance gamma-alpha would require a larger table.) 17480 17481 // NB: 17482 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. 17483 17484 constexpr int kCachedPowersMinDecExp = -300; 17485 constexpr int kCachedPowersDecStep = 8; 17486 17487 static constexpr std::array<cached_power, 79> kCachedPowers = 17488 { 17489 { 17490 { 0xAB70FE17C79AC6CA, -1060, -300 }, 17491 { 0xFF77B1FCBEBCDC4F, -1034, -292 }, 17492 { 0xBE5691EF416BD60C, -1007, -284 }, 17493 { 0x8DD01FAD907FFC3C, -980, -276 }, 17494 { 0xD3515C2831559A83, -954, -268 }, 17495 { 0x9D71AC8FADA6C9B5, -927, -260 }, 17496 { 0xEA9C227723EE8BCB, -901, -252 }, 17497 { 0xAECC49914078536D, -874, -244 }, 17498 { 0x823C12795DB6CE57, -847, -236 }, 17499 { 0xC21094364DFB5637, -821, -228 }, 17500 { 0x9096EA6F3848984F, -794, -220 }, 17501 { 0xD77485CB25823AC7, -768, -212 }, 17502 { 0xA086CFCD97BF97F4, -741, -204 }, 17503 { 0xEF340A98172AACE5, -715, -196 }, 17504 { 0xB23867FB2A35B28E, -688, -188 }, 17505 { 0x84C8D4DFD2C63F3B, -661, -180 }, 17506 { 0xC5DD44271AD3CDBA, -635, -172 }, 17507 { 0x936B9FCEBB25C996, -608, -164 }, 17508 { 0xDBAC6C247D62A584, -582, -156 }, 17509 { 0xA3AB66580D5FDAF6, -555, -148 }, 17510 { 0xF3E2F893DEC3F126, -529, -140 }, 17511 { 0xB5B5ADA8AAFF80B8, -502, -132 }, 17512 { 0x87625F056C7C4A8B, -475, -124 }, 17513 { 0xC9BCFF6034C13053, -449, -116 }, 17514 { 0x964E858C91BA2655, -422, -108 }, 17515 { 0xDFF9772470297EBD, -396, -100 }, 17516 { 0xA6DFBD9FB8E5B88F, -369, -92 }, 17517 { 0xF8A95FCF88747D94, -343, -84 }, 17518 { 0xB94470938FA89BCF, -316, -76 }, 17519 { 0x8A08F0F8BF0F156B, -289, -68 }, 17520 { 0xCDB02555653131B6, -263, -60 }, 17521 { 0x993FE2C6D07B7FAC, -236, -52 }, 17522 { 0xE45C10C42A2B3B06, -210, -44 }, 17523 { 0xAA242499697392D3, -183, -36 }, 17524 { 0xFD87B5F28300CA0E, -157, -28 }, 17525 { 0xBCE5086492111AEB, -130, -20 }, 17526 { 0x8CBCCC096F5088CC, -103, -12 }, 17527 { 0xD1B71758E219652C, -77, -4 }, 17528 { 0x9C40000000000000, -50, 4 }, 17529 { 0xE8D4A51000000000, -24, 12 }, 17530 { 0xAD78EBC5AC620000, 3, 20 }, 17531 { 0x813F3978F8940984, 30, 28 }, 17532 { 0xC097CE7BC90715B3, 56, 36 }, 17533 { 0x8F7E32CE7BEA5C70, 83, 44 }, 17534 { 0xD5D238A4ABE98068, 109, 52 }, 17535 { 0x9F4F2726179A2245, 136, 60 }, 17536 { 0xED63A231D4C4FB27, 162, 68 }, 17537 { 0xB0DE65388CC8ADA8, 189, 76 }, 17538 { 0x83C7088E1AAB65DB, 216, 84 }, 17539 { 0xC45D1DF942711D9A, 242, 92 }, 17540 { 0x924D692CA61BE758, 269, 100 }, 17541 { 0xDA01EE641A708DEA, 295, 108 }, 17542 { 0xA26DA3999AEF774A, 322, 116 }, 17543 { 0xF209787BB47D6B85, 348, 124 }, 17544 { 0xB454E4A179DD1877, 375, 132 }, 17545 { 0x865B86925B9BC5C2, 402, 140 }, 17546 { 0xC83553C5C8965D3D, 428, 148 }, 17547 { 0x952AB45CFA97A0B3, 455, 156 }, 17548 { 0xDE469FBD99A05FE3, 481, 164 }, 17549 { 0xA59BC234DB398C25, 508, 172 }, 17550 { 0xF6C69A72A3989F5C, 534, 180 }, 17551 { 0xB7DCBF5354E9BECE, 561, 188 }, 17552 { 0x88FCF317F22241E2, 588, 196 }, 17553 { 0xCC20CE9BD35C78A5, 614, 204 }, 17554 { 0x98165AF37B2153DF, 641, 212 }, 17555 { 0xE2A0B5DC971F303A, 667, 220 }, 17556 { 0xA8D9D1535CE3B396, 694, 228 }, 17557 { 0xFB9B7CD9A4A7443C, 720, 236 }, 17558 { 0xBB764C4CA7A44410, 747, 244 }, 17559 { 0x8BAB8EEFB6409C1A, 774, 252 }, 17560 { 0xD01FEF10A657842C, 800, 260 }, 17561 { 0x9B10A4E5E9913129, 827, 268 }, 17562 { 0xE7109BFBA19C0C9D, 853, 276 }, 17563 { 0xAC2820D9623BF429, 880, 284 }, 17564 { 0x80444B5E7AA7CF85, 907, 292 }, 17565 { 0xBF21E44003ACDD2D, 933, 300 }, 17566 { 0x8E679C2F5E44FF8F, 960, 308 }, 17567 { 0xD433179D9C8CB841, 986, 316 }, 17568 { 0x9E19DB92B4E31BA9, 1013, 324 }, 17569 } 17570 }; 17571 17572 // This computation gives exactly the same results for k as 17573 // k = ceil((kAlpha - e - 1) * 0.30102999566398114) 17574 // for |e| <= 1500, but doesn't require floating-point operations. 17575 // NB: log_10(2) ~= 78913 / 2^18 17576 JSON_ASSERT(e >= -1500); 17577 JSON_ASSERT(e <= 1500); 17578 const int f = kAlpha - e - 1; 17579 const int k = ((f * 78913) / (1 << 18)) + static_cast<int>(f > 0); 17580 17581 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; 17582 JSON_ASSERT(index >= 0); 17583 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size()); 17584 17585 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)]; 17586 JSON_ASSERT(kAlpha <= cached.e + e + 64); 17587 JSON_ASSERT(kGamma >= cached.e + e + 64); 17588 17589 return cached; 17590 } 17591 17592 /*! 17593 For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. 17594 For n == 0, returns 1 and sets pow10 := 1. 17595 */ 17596 inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) 17597 { 17598 // LCOV_EXCL_START 17599 if (n >= 1000000000) 17600 { 17601 pow10 = 1000000000; 17602 return 10; 17603 } 17604 // LCOV_EXCL_STOP 17605 if (n >= 100000000) 17606 { 17607 pow10 = 100000000; 17608 return 9; 17609 } 17610 if (n >= 10000000) 17611 { 17612 pow10 = 10000000; 17613 return 8; 17614 } 17615 if (n >= 1000000) 17616 { 17617 pow10 = 1000000; 17618 return 7; 17619 } 17620 if (n >= 100000) 17621 { 17622 pow10 = 100000; 17623 return 6; 17624 } 17625 if (n >= 10000) 17626 { 17627 pow10 = 10000; 17628 return 5; 17629 } 17630 if (n >= 1000) 17631 { 17632 pow10 = 1000; 17633 return 4; 17634 } 17635 if (n >= 100) 17636 { 17637 pow10 = 100; 17638 return 3; 17639 } 17640 if (n >= 10) 17641 { 17642 pow10 = 10; 17643 return 2; 17644 } 17645 17646 pow10 = 1; 17647 return 1; 17648 } 17649 17650 inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, 17651 std::uint64_t rest, std::uint64_t ten_k) 17652 { 17653 JSON_ASSERT(len >= 1); 17654 JSON_ASSERT(dist <= delta); 17655 JSON_ASSERT(rest <= delta); 17656 JSON_ASSERT(ten_k > 0); 17657 17658 // <--------------------------- delta ----> 17659 // <---- dist ---------> 17660 // --------------[------------------+-------------------]-------------- 17661 // M- w M+ 17662 // 17663 // ten_k 17664 // <------> 17665 // <---- rest ----> 17666 // --------------[------------------+----+--------------]-------------- 17667 // w V 17668 // = buf * 10^k 17669 // 17670 // ten_k represents a unit-in-the-last-place in the decimal representation 17671 // stored in buf. 17672 // Decrement buf by ten_k while this takes buf closer to w. 17673 17674 // The tests are written in this order to avoid overflow in unsigned 17675 // integer arithmetic. 17676 17677 while (rest < dist 17678 && delta - rest >= ten_k 17679 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) 17680 { 17681 JSON_ASSERT(buf[len - 1] != '0'); 17682 buf[len - 1]--; 17683 rest += ten_k; 17684 } 17685 } 17686 17687 /*! 17688 Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. 17689 M- and M+ must be normalized and share the same exponent -60 <= e <= -32. 17690 */ 17691 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, 17692 diyfp M_minus, diyfp w, diyfp M_plus) 17693 { 17694 static_assert(kAlpha >= -60, "internal error"); 17695 static_assert(kGamma <= -32, "internal error"); 17696 17697 // Generates the digits (and the exponent) of a decimal floating-point 17698 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's 17699 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. 17700 // 17701 // <--------------------------- delta ----> 17702 // <---- dist ---------> 17703 // --------------[------------------+-------------------]-------------- 17704 // M- w M+ 17705 // 17706 // Grisu2 generates the digits of M+ from left to right and stops as soon as 17707 // V is in [M-,M+]. 17708 17709 JSON_ASSERT(M_plus.e >= kAlpha); 17710 JSON_ASSERT(M_plus.e <= kGamma); 17711 17712 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) 17713 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e) 17714 17715 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): 17716 // 17717 // M+ = f * 2^e 17718 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e 17719 // = ((p1 ) * 2^-e + (p2 )) * 2^e 17720 // = p1 + p2 * 2^e 17721 17722 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e); 17723 17724 auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.) 17725 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e 17726 17727 // 1) 17728 // 17729 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] 17730 17731 JSON_ASSERT(p1 > 0); 17732 17733 std::uint32_t pow10{}; 17734 const int k = find_largest_pow10(p1, pow10); 17735 17736 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) 17737 // 17738 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) 17739 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) 17740 // 17741 // M+ = p1 + p2 * 2^e 17742 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e 17743 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e 17744 // = d[k-1] * 10^(k-1) + ( rest) * 2^e 17745 // 17746 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) 17747 // 17748 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] 17749 // 17750 // but stop as soon as 17751 // 17752 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e 17753 17754 int n = k; 17755 while (n > 0) 17756 { 17757 // Invariants: 17758 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) 17759 // pow10 = 10^(n-1) <= p1 < 10^n 17760 // 17761 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) 17762 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) 17763 // 17764 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e 17765 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) 17766 // 17767 JSON_ASSERT(d <= 9); 17768 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d 17769 // 17770 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) 17771 // 17772 p1 = r; 17773 n--; 17774 // 17775 // M+ = buffer * 10^n + (p1 + p2 * 2^e) 17776 // pow10 = 10^n 17777 // 17778 17779 // Now check if enough digits have been generated. 17780 // Compute 17781 // 17782 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e 17783 // 17784 // Note: 17785 // Since rest and delta share the same exponent e, it suffices to 17786 // compare the significands. 17787 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2; 17788 if (rest <= delta) 17789 { 17790 // V = buffer * 10^n, with M- <= V <= M+. 17791 17792 decimal_exponent += n; 17793 17794 // We may now just stop. But instead look if the buffer could be 17795 // decremented to bring V closer to w. 17796 // 17797 // pow10 = 10^n is now 1 ulp in the decimal representation V. 17798 // The rounding procedure works with diyfp's with an implicit 17799 // exponent of e. 17800 // 17801 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e 17802 // 17803 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e; 17804 grisu2_round(buffer, length, dist, delta, rest, ten_n); 17805 17806 return; 17807 } 17808 17809 pow10 /= 10; 17810 // 17811 // pow10 = 10^(n-1) <= p1 < 10^n 17812 // Invariants restored. 17813 } 17814 17815 // 2) 17816 // 17817 // The digits of the integral part have been generated: 17818 // 17819 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e 17820 // = buffer + p2 * 2^e 17821 // 17822 // Now generate the digits of the fractional part p2 * 2^e. 17823 // 17824 // Note: 17825 // No decimal point is generated: the exponent is adjusted instead. 17826 // 17827 // p2 actually represents the fraction 17828 // 17829 // p2 * 2^e 17830 // = p2 / 2^-e 17831 // = d[-1] / 10^1 + d[-2] / 10^2 + ... 17832 // 17833 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) 17834 // 17835 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m 17836 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) 17837 // 17838 // using 17839 // 17840 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) 17841 // = ( d) * 2^-e + ( r) 17842 // 17843 // or 17844 // 10^m * p2 * 2^e = d + r * 2^e 17845 // 17846 // i.e. 17847 // 17848 // M+ = buffer + p2 * 2^e 17849 // = buffer + 10^-m * (d + r * 2^e) 17850 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e 17851 // 17852 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e 17853 17854 JSON_ASSERT(p2 > delta); 17855 17856 int m = 0; 17857 for (;;) 17858 { 17859 // Invariant: 17860 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e 17861 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e 17862 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e 17863 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e 17864 // 17865 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10); 17866 p2 *= 10; 17867 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e 17868 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e 17869 // 17870 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e 17871 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) 17872 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e 17873 // 17874 JSON_ASSERT(d <= 9); 17875 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d 17876 // 17877 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e 17878 // 17879 p2 = r; 17880 m++; 17881 // 17882 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e 17883 // Invariant restored. 17884 17885 // Check if enough digits have been generated. 17886 // 17887 // 10^-m * p2 * 2^e <= delta * 2^e 17888 // p2 * 2^e <= 10^m * delta * 2^e 17889 // p2 <= 10^m * delta 17890 delta *= 10; 17891 dist *= 10; 17892 if (p2 <= delta) 17893 { 17894 break; 17895 } 17896 } 17897 17898 // V = buffer * 10^-m, with M- <= V <= M+. 17899 17900 decimal_exponent -= m; 17901 17902 // 1 ulp in the decimal representation is now 10^-m. 17903 // Since delta and dist are now scaled by 10^m, we need to do the 17904 // same with ulp in order to keep the units in sync. 17905 // 17906 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e 17907 // 17908 const std::uint64_t ten_m = one.f; 17909 grisu2_round(buffer, length, dist, delta, p2, ten_m); 17910 17911 // By construction this algorithm generates the shortest possible decimal 17912 // number (Loitsch, Theorem 6.2) which rounds back to w. 17913 // For an input number of precision p, at least 17914 // 17915 // N = 1 + ceil(p * log_10(2)) 17916 // 17917 // decimal digits are sufficient to identify all binary floating-point 17918 // numbers (Matula, "In-and-Out conversions"). 17919 // This implies that the algorithm does not produce more than N decimal 17920 // digits. 17921 // 17922 // N = 17 for p = 53 (IEEE double precision) 17923 // N = 9 for p = 24 (IEEE single precision) 17924 } 17925 17926 /*! 17927 v = buf * 10^decimal_exponent 17928 len is the length of the buffer (number of decimal digits) 17929 The buffer must be large enough, i.e. >= max_digits10. 17930 */ 17931 JSON_HEDLEY_NON_NULL(1) 17932 inline void grisu2(char* buf, int& len, int& decimal_exponent, 17933 diyfp m_minus, diyfp v, diyfp m_plus) 17934 { 17935 JSON_ASSERT(m_plus.e == m_minus.e); 17936 JSON_ASSERT(m_plus.e == v.e); 17937 17938 // --------(-----------------------+-----------------------)-------- (A) 17939 // m- v m+ 17940 // 17941 // --------------------(-----------+-----------------------)-------- (B) 17942 // m- v m+ 17943 // 17944 // First scale v (and m- and m+) such that the exponent is in the range 17945 // [alpha, gamma]. 17946 17947 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); 17948 17949 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k 17950 17951 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] 17952 const diyfp w = diyfp::mul(v, c_minus_k); 17953 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); 17954 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); 17955 17956 // ----(---+---)---------------(---+---)---------------(---+---)---- 17957 // w- w w+ 17958 // = c*m- = c*v = c*m+ 17959 // 17960 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and 17961 // w+ are now off by a small amount. 17962 // In fact: 17963 // 17964 // w - v * 10^k < 1 ulp 17965 // 17966 // To account for this inaccuracy, add resp. subtract 1 ulp. 17967 // 17968 // --------+---[---------------(---+---)---------------]---+-------- 17969 // w- M- w M+ w+ 17970 // 17971 // Now any number in [M-, M+] (bounds included) will round to w when input, 17972 // regardless of how the input rounding algorithm breaks ties. 17973 // 17974 // And digit_gen generates the shortest possible such number in [M-, M+]. 17975 // Note that this does not mean that Grisu2 always generates the shortest 17976 // possible number in the interval (m-, m+). 17977 const diyfp M_minus(w_minus.f + 1, w_minus.e); 17978 const diyfp M_plus (w_plus.f - 1, w_plus.e ); 17979 17980 decimal_exponent = -cached.k; // = -(-k) = k 17981 17982 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); 17983 } 17984 17985 /*! 17986 v = buf * 10^decimal_exponent 17987 len is the length of the buffer (number of decimal digits) 17988 The buffer must be large enough, i.e. >= max_digits10. 17989 */ 17990 template<typename FloatType> 17991 JSON_HEDLEY_NON_NULL(1) 17992 void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) 17993 { 17994 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3, 17995 "internal error: not enough precision"); 17996 17997 JSON_ASSERT(std::isfinite(value)); 17998 JSON_ASSERT(value > 0); 17999 18000 // If the neighbors (and boundaries) of 'value' are always computed for double-precision 18001 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting 18002 // decimal representations are not exactly "short". 18003 // 18004 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) 18005 // says "value is converted to a string as if by std::sprintf in the default ("C") locale" 18006 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars' 18007 // does. 18008 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the 18009 // representation using the corresponding std::from_chars function recovers value exactly". That 18010 // indicates that single precision floating-point numbers should be recovered using 18011 // 'std::strtof'. 18012 // 18013 // NB: If the neighbors are computed for single-precision numbers, there is a single float 18014 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision 18015 // value is off by 1 ulp. 18016 #if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if) 18017 const boundaries w = compute_boundaries(static_cast<double>(value)); 18018 #else 18019 const boundaries w = compute_boundaries(value); 18020 #endif 18021 18022 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); 18023 } 18024 18025 /*! 18026 @brief appends a decimal representation of e to buf 18027 @return a pointer to the element following the exponent. 18028 @pre -1000 < e < 1000 18029 */ 18030 JSON_HEDLEY_NON_NULL(1) 18031 JSON_HEDLEY_RETURNS_NON_NULL 18032 inline char* append_exponent(char* buf, int e) 18033 { 18034 JSON_ASSERT(e > -1000); 18035 JSON_ASSERT(e < 1000); 18036 18037 if (e < 0) 18038 { 18039 e = -e; 18040 *buf++ = '-'; 18041 } 18042 else 18043 { 18044 *buf++ = '+'; 18045 } 18046 18047 auto k = static_cast<std::uint32_t>(e); 18048 if (k < 10) 18049 { 18050 // Always print at least two digits in the exponent. 18051 // This is for compatibility with printf("%g"). 18052 *buf++ = '0'; 18053 *buf++ = static_cast<char>('0' + k); 18054 } 18055 else if (k < 100) 18056 { 18057 *buf++ = static_cast<char>('0' + (k / 10)); 18058 k %= 10; 18059 *buf++ = static_cast<char>('0' + k); 18060 } 18061 else 18062 { 18063 *buf++ = static_cast<char>('0' + (k / 100)); 18064 k %= 100; 18065 *buf++ = static_cast<char>('0' + (k / 10)); 18066 k %= 10; 18067 *buf++ = static_cast<char>('0' + k); 18068 } 18069 18070 return buf; 18071 } 18072 18073 /*! 18074 @brief prettify v = buf * 10^decimal_exponent 18075 18076 If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point 18077 notation. Otherwise it will be printed in exponential notation. 18078 18079 @pre min_exp < 0 18080 @pre max_exp > 0 18081 */ 18082 JSON_HEDLEY_NON_NULL(1) 18083 JSON_HEDLEY_RETURNS_NON_NULL 18084 inline char* format_buffer(char* buf, int len, int decimal_exponent, 18085 int min_exp, int max_exp) 18086 { 18087 JSON_ASSERT(min_exp < 0); 18088 JSON_ASSERT(max_exp > 0); 18089 18090 const int k = len; 18091 const int n = len + decimal_exponent; 18092 18093 // v = buf * 10^(n-k) 18094 // k is the length of the buffer (number of decimal digits) 18095 // n is the position of the decimal point relative to the start of the buffer. 18096 18097 if (k <= n && n <= max_exp) 18098 { 18099 // digits[000] 18100 // len <= max_exp + 2 18101 18102 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k)); 18103 // Make it look like a floating-point number (#362, #378) 18104 buf[n + 0] = '.'; 18105 buf[n + 1] = '0'; 18106 return buf + (static_cast<size_t>(n) + 2); 18107 } 18108 18109 if (0 < n && n <= max_exp) 18110 { 18111 // dig.its 18112 // len <= max_digits10 + 1 18113 18114 JSON_ASSERT(k > n); 18115 18116 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n)); 18117 buf[n] = '.'; 18118 return buf + (static_cast<size_t>(k) + 1U); 18119 } 18120 18121 if (min_exp < n && n <= 0) 18122 { 18123 // 0.[000]digits 18124 // len <= 2 + (-min_exp - 1) + max_digits10 18125 18126 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k)); 18127 buf[0] = '0'; 18128 buf[1] = '.'; 18129 std::memset(buf + 2, '0', static_cast<size_t>(-n)); 18130 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k)); 18131 } 18132 18133 if (k == 1) 18134 { 18135 // dE+123 18136 // len <= 1 + 5 18137 18138 buf += 1; 18139 } 18140 else 18141 { 18142 // d.igitsE+123 18143 // len <= max_digits10 + 1 + 5 18144 18145 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1); 18146 buf[1] = '.'; 18147 buf += 1 + static_cast<size_t>(k); 18148 } 18149 18150 *buf++ = 'e'; 18151 return append_exponent(buf, n - 1); 18152 } 18153 18154 } // namespace dtoa_impl 18155 18156 /*! 18157 @brief generates a decimal representation of the floating-point number value in [first, last). 18158 18159 The format of the resulting decimal representation is similar to printf's %g 18160 format. Returns an iterator pointing past-the-end of the decimal representation. 18161 18162 @note The input number must be finite, i.e. NaN's and Inf's are not supported. 18163 @note The buffer must be large enough. 18164 @note The result is NOT null-terminated. 18165 */ 18166 template<typename FloatType> 18167 JSON_HEDLEY_NON_NULL(1, 2) 18168 JSON_HEDLEY_RETURNS_NON_NULL 18169 char* to_chars(char* first, const char* last, FloatType value) 18170 { 18171 static_cast<void>(last); // maybe unused - fix warning 18172 JSON_ASSERT(std::isfinite(value)); 18173 18174 // Use signbit(value) instead of (value < 0) since signbit works for -0. 18175 if (std::signbit(value)) 18176 { 18177 value = -value; 18178 *first++ = '-'; 18179 } 18180 18181 #ifdef __GNUC__ 18182 #pragma GCC diagnostic push 18183 #pragma GCC diagnostic ignored "-Wfloat-equal" 18184 #endif 18185 if (value == 0) // +-0 18186 { 18187 *first++ = '0'; 18188 // Make it look like a floating-point number (#362, #378) 18189 *first++ = '.'; 18190 *first++ = '0'; 18191 return first; 18192 } 18193 #ifdef __GNUC__ 18194 #pragma GCC diagnostic pop 18195 #endif 18196 18197 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10); 18198 18199 // Compute v = buffer * 10^decimal_exponent. 18200 // The decimal digits are stored in the buffer, which needs to be interpreted 18201 // as an unsigned decimal integer. 18202 // len is the length of the buffer, i.e. the number of decimal digits. 18203 int len = 0; 18204 int decimal_exponent = 0; 18205 dtoa_impl::grisu2(first, len, decimal_exponent, value); 18206 18207 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10); 18208 18209 // Format the buffer like printf("%.*g", prec, value) 18210 constexpr int kMinExp = -4; 18211 // Use digits10 here to increase compatibility with version 2. 18212 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10; 18213 18214 JSON_ASSERT(last - first >= kMaxExp + 2); 18215 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10); 18216 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6); 18217 18218 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); 18219 } 18220 18221 } // namespace detail 18222 NLOHMANN_JSON_NAMESPACE_END 18223 18224 // #include <nlohmann/detail/exceptions.hpp> 18225 18226 // #include <nlohmann/detail/macro_scope.hpp> 18227 18228 // #include <nlohmann/detail/meta/cpp_future.hpp> 18229 18230 // #include <nlohmann/detail/output/binary_writer.hpp> 18231 18232 // #include <nlohmann/detail/output/output_adapters.hpp> 18233 18234 // #include <nlohmann/detail/string_concat.hpp> 18235 18236 // #include <nlohmann/detail/value_t.hpp> 18237 18238 18239 NLOHMANN_JSON_NAMESPACE_BEGIN 18240 namespace detail 18241 { 18242 18243 /////////////////// 18244 // serialization // 18245 /////////////////// 18246 18247 /// how to treat decoding errors 18248 enum class error_handler_t 18249 { 18250 strict, ///< throw a type_error exception in case of invalid UTF-8 18251 replace, ///< replace invalid UTF-8 sequences with U+FFFD 18252 ignore ///< ignore invalid UTF-8 sequences 18253 }; 18254 18255 template<typename BasicJsonType> 18256 class serializer 18257 { 18258 using string_t = typename BasicJsonType::string_t; 18259 using number_float_t = typename BasicJsonType::number_float_t; 18260 using number_integer_t = typename BasicJsonType::number_integer_t; 18261 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 18262 using binary_char_t = typename BasicJsonType::binary_t::value_type; 18263 static constexpr std::uint8_t UTF8_ACCEPT = 0; 18264 static constexpr std::uint8_t UTF8_REJECT = 1; 18265 18266 public: 18267 /*! 18268 @param[in] s output stream to serialize to 18269 @param[in] ichar indentation character to use 18270 @param[in] error_handler_ how to react on decoding errors 18271 */ 18272 serializer(output_adapter_t<char> s, const char ichar, 18273 error_handler_t error_handler_ = error_handler_t::strict) 18274 : o(std::move(s)) 18275 , loc(std::localeconv()) 18276 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep))) 18277 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point))) 18278 , indent_char(ichar) 18279 , indent_string(512, indent_char) 18280 , error_handler(error_handler_) 18281 {} 18282 18283 // delete because of pointer members 18284 serializer(const serializer&) = delete; 18285 serializer& operator=(const serializer&) = delete; 18286 serializer(serializer&&) = delete; 18287 serializer& operator=(serializer&&) = delete; 18288 ~serializer() = default; 18289 18290 /*! 18291 @brief internal implementation of the serialization function 18292 18293 This function is called by the public member function dump and organizes 18294 the serialization internally. The indentation level is propagated as 18295 additional parameter. In case of arrays and objects, the function is 18296 called recursively. 18297 18298 - strings and object keys are escaped using `escape_string()` 18299 - integer numbers are converted implicitly via `operator<<` 18300 - floating-point numbers are converted to a string using `"%g"` format 18301 - binary values are serialized as objects containing the subtype and the 18302 byte array 18303 18304 @param[in] val value to serialize 18305 @param[in] pretty_print whether the output shall be pretty-printed 18306 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters 18307 in the output are escaped with `\uXXXX` sequences, and the result consists 18308 of ASCII characters only. 18309 @param[in] indent_step the indent level 18310 @param[in] current_indent the current indent level (only used internally) 18311 */ 18312 void dump(const BasicJsonType& val, 18313 const bool pretty_print, 18314 const bool ensure_ascii, 18315 const unsigned int indent_step, 18316 const unsigned int current_indent = 0) 18317 { 18318 switch (val.m_data.m_type) 18319 { 18320 case value_t::object: 18321 { 18322 if (val.m_data.m_value.object->empty()) 18323 { 18324 o->write_characters("{}", 2); 18325 return; 18326 } 18327 18328 if (pretty_print) 18329 { 18330 o->write_characters("{\n", 2); 18331 18332 // variable to hold indentation for recursive calls 18333 const auto new_indent = current_indent + indent_step; 18334 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) 18335 { 18336 indent_string.resize(indent_string.size() * 2, ' '); 18337 } 18338 18339 // first n-1 elements 18340 auto i = val.m_data.m_value.object->cbegin(); 18341 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) 18342 { 18343 o->write_characters(indent_string.c_str(), new_indent); 18344 o->write_character('\"'); 18345 dump_escaped(i->first, ensure_ascii); 18346 o->write_characters("\": ", 3); 18347 dump(i->second, true, ensure_ascii, indent_step, new_indent); 18348 o->write_characters(",\n", 2); 18349 } 18350 18351 // last element 18352 JSON_ASSERT(i != val.m_data.m_value.object->cend()); 18353 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend()); 18354 o->write_characters(indent_string.c_str(), new_indent); 18355 o->write_character('\"'); 18356 dump_escaped(i->first, ensure_ascii); 18357 o->write_characters("\": ", 3); 18358 dump(i->second, true, ensure_ascii, indent_step, new_indent); 18359 18360 o->write_character('\n'); 18361 o->write_characters(indent_string.c_str(), current_indent); 18362 o->write_character('}'); 18363 } 18364 else 18365 { 18366 o->write_character('{'); 18367 18368 // first n-1 elements 18369 auto i = val.m_data.m_value.object->cbegin(); 18370 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) 18371 { 18372 o->write_character('\"'); 18373 dump_escaped(i->first, ensure_ascii); 18374 o->write_characters("\":", 2); 18375 dump(i->second, false, ensure_ascii, indent_step, current_indent); 18376 o->write_character(','); 18377 } 18378 18379 // last element 18380 JSON_ASSERT(i != val.m_data.m_value.object->cend()); 18381 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend()); 18382 o->write_character('\"'); 18383 dump_escaped(i->first, ensure_ascii); 18384 o->write_characters("\":", 2); 18385 dump(i->second, false, ensure_ascii, indent_step, current_indent); 18386 18387 o->write_character('}'); 18388 } 18389 18390 return; 18391 } 18392 18393 case value_t::array: 18394 { 18395 if (val.m_data.m_value.array->empty()) 18396 { 18397 o->write_characters("[]", 2); 18398 return; 18399 } 18400 18401 if (pretty_print) 18402 { 18403 o->write_characters("[\n", 2); 18404 18405 // variable to hold indentation for recursive calls 18406 const auto new_indent = current_indent + indent_step; 18407 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) 18408 { 18409 indent_string.resize(indent_string.size() * 2, ' '); 18410 } 18411 18412 // first n-1 elements 18413 for (auto i = val.m_data.m_value.array->cbegin(); 18414 i != val.m_data.m_value.array->cend() - 1; ++i) 18415 { 18416 o->write_characters(indent_string.c_str(), new_indent); 18417 dump(*i, true, ensure_ascii, indent_step, new_indent); 18418 o->write_characters(",\n", 2); 18419 } 18420 18421 // last element 18422 JSON_ASSERT(!val.m_data.m_value.array->empty()); 18423 o->write_characters(indent_string.c_str(), new_indent); 18424 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); 18425 18426 o->write_character('\n'); 18427 o->write_characters(indent_string.c_str(), current_indent); 18428 o->write_character(']'); 18429 } 18430 else 18431 { 18432 o->write_character('['); 18433 18434 // first n-1 elements 18435 for (auto i = val.m_data.m_value.array->cbegin(); 18436 i != val.m_data.m_value.array->cend() - 1; ++i) 18437 { 18438 dump(*i, false, ensure_ascii, indent_step, current_indent); 18439 o->write_character(','); 18440 } 18441 18442 // last element 18443 JSON_ASSERT(!val.m_data.m_value.array->empty()); 18444 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); 18445 18446 o->write_character(']'); 18447 } 18448 18449 return; 18450 } 18451 18452 case value_t::string: 18453 { 18454 o->write_character('\"'); 18455 dump_escaped(*val.m_data.m_value.string, ensure_ascii); 18456 o->write_character('\"'); 18457 return; 18458 } 18459 18460 case value_t::binary: 18461 { 18462 if (pretty_print) 18463 { 18464 o->write_characters("{\n", 2); 18465 18466 // variable to hold indentation for recursive calls 18467 const auto new_indent = current_indent + indent_step; 18468 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) 18469 { 18470 indent_string.resize(indent_string.size() * 2, ' '); 18471 } 18472 18473 o->write_characters(indent_string.c_str(), new_indent); 18474 18475 o->write_characters("\"bytes\": [", 10); 18476 18477 if (!val.m_data.m_value.binary->empty()) 18478 { 18479 for (auto i = val.m_data.m_value.binary->cbegin(); 18480 i != val.m_data.m_value.binary->cend() - 1; ++i) 18481 { 18482 dump_integer(*i); 18483 o->write_characters(", ", 2); 18484 } 18485 dump_integer(val.m_data.m_value.binary->back()); 18486 } 18487 18488 o->write_characters("],\n", 3); 18489 o->write_characters(indent_string.c_str(), new_indent); 18490 18491 o->write_characters("\"subtype\": ", 11); 18492 if (val.m_data.m_value.binary->has_subtype()) 18493 { 18494 dump_integer(val.m_data.m_value.binary->subtype()); 18495 } 18496 else 18497 { 18498 o->write_characters("null", 4); 18499 } 18500 o->write_character('\n'); 18501 o->write_characters(indent_string.c_str(), current_indent); 18502 o->write_character('}'); 18503 } 18504 else 18505 { 18506 o->write_characters("{\"bytes\":[", 10); 18507 18508 if (!val.m_data.m_value.binary->empty()) 18509 { 18510 for (auto i = val.m_data.m_value.binary->cbegin(); 18511 i != val.m_data.m_value.binary->cend() - 1; ++i) 18512 { 18513 dump_integer(*i); 18514 o->write_character(','); 18515 } 18516 dump_integer(val.m_data.m_value.binary->back()); 18517 } 18518 18519 o->write_characters("],\"subtype\":", 12); 18520 if (val.m_data.m_value.binary->has_subtype()) 18521 { 18522 dump_integer(val.m_data.m_value.binary->subtype()); 18523 o->write_character('}'); 18524 } 18525 else 18526 { 18527 o->write_characters("null}", 5); 18528 } 18529 } 18530 return; 18531 } 18532 18533 case value_t::boolean: 18534 { 18535 if (val.m_data.m_value.boolean) 18536 { 18537 o->write_characters("true", 4); 18538 } 18539 else 18540 { 18541 o->write_characters("false", 5); 18542 } 18543 return; 18544 } 18545 18546 case value_t::number_integer: 18547 { 18548 dump_integer(val.m_data.m_value.number_integer); 18549 return; 18550 } 18551 18552 case value_t::number_unsigned: 18553 { 18554 dump_integer(val.m_data.m_value.number_unsigned); 18555 return; 18556 } 18557 18558 case value_t::number_float: 18559 { 18560 dump_float(val.m_data.m_value.number_float); 18561 return; 18562 } 18563 18564 case value_t::discarded: 18565 { 18566 o->write_characters("<discarded>", 11); 18567 return; 18568 } 18569 18570 case value_t::null: 18571 { 18572 o->write_characters("null", 4); 18573 return; 18574 } 18575 18576 default: // LCOV_EXCL_LINE 18577 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 18578 } 18579 } 18580 18581 JSON_PRIVATE_UNLESS_TESTED: 18582 /*! 18583 @brief dump escaped string 18584 18585 Escape a string by replacing certain special characters by a sequence of an 18586 escape character (backslash) and another character and other control 18587 characters by a sequence of "\u" followed by a four-digit hex 18588 representation. The escaped string is written to output stream @a o. 18589 18590 @param[in] s the string to escape 18591 @param[in] ensure_ascii whether to escape non-ASCII characters with 18592 \uXXXX sequences 18593 18594 @complexity Linear in the length of string @a s. 18595 */ 18596 void dump_escaped(const string_t& s, const bool ensure_ascii) 18597 { 18598 std::uint32_t codepoint{}; 18599 std::uint8_t state = UTF8_ACCEPT; 18600 std::size_t bytes = 0; // number of bytes written to string_buffer 18601 18602 // number of bytes written at the point of the last valid byte 18603 std::size_t bytes_after_last_accept = 0; 18604 std::size_t undumped_chars = 0; 18605 18606 for (std::size_t i = 0; i < s.size(); ++i) 18607 { 18608 const auto byte = static_cast<std::uint8_t>(s[i]); 18609 18610 switch (decode(state, codepoint, byte)) 18611 { 18612 case UTF8_ACCEPT: // decode found a new code point 18613 { 18614 switch (codepoint) 18615 { 18616 case 0x08: // backspace 18617 { 18618 string_buffer[bytes++] = '\\'; 18619 string_buffer[bytes++] = 'b'; 18620 break; 18621 } 18622 18623 case 0x09: // horizontal tab 18624 { 18625 string_buffer[bytes++] = '\\'; 18626 string_buffer[bytes++] = 't'; 18627 break; 18628 } 18629 18630 case 0x0A: // newline 18631 { 18632 string_buffer[bytes++] = '\\'; 18633 string_buffer[bytes++] = 'n'; 18634 break; 18635 } 18636 18637 case 0x0C: // formfeed 18638 { 18639 string_buffer[bytes++] = '\\'; 18640 string_buffer[bytes++] = 'f'; 18641 break; 18642 } 18643 18644 case 0x0D: // carriage return 18645 { 18646 string_buffer[bytes++] = '\\'; 18647 string_buffer[bytes++] = 'r'; 18648 break; 18649 } 18650 18651 case 0x22: // quotation mark 18652 { 18653 string_buffer[bytes++] = '\\'; 18654 string_buffer[bytes++] = '\"'; 18655 break; 18656 } 18657 18658 case 0x5C: // reverse solidus 18659 { 18660 string_buffer[bytes++] = '\\'; 18661 string_buffer[bytes++] = '\\'; 18662 break; 18663 } 18664 18665 default: 18666 { 18667 // escape control characters (0x00..0x1F) or, if 18668 // ensure_ascii parameter is used, non-ASCII characters 18669 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) 18670 { 18671 if (codepoint <= 0xFFFF) 18672 { 18673 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 18674 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x", 18675 static_cast<std::uint16_t>(codepoint))); 18676 bytes += 6; 18677 } 18678 else 18679 { 18680 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 18681 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x", 18682 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)), 18683 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)))); 18684 bytes += 12; 18685 } 18686 } 18687 else 18688 { 18689 // copy byte to buffer (all previous bytes 18690 // been copied have in default case above) 18691 string_buffer[bytes++] = s[i]; 18692 } 18693 break; 18694 } 18695 } 18696 18697 // write buffer and reset index; there must be 13 bytes 18698 // left, as this is the maximal number of bytes to be 18699 // written ("\uxxxx\uxxxx\0") for one code point 18700 if (string_buffer.size() - bytes < 13) 18701 { 18702 o->write_characters(string_buffer.data(), bytes); 18703 bytes = 0; 18704 } 18705 18706 // remember the byte position of this accept 18707 bytes_after_last_accept = bytes; 18708 undumped_chars = 0; 18709 break; 18710 } 18711 18712 case UTF8_REJECT: // decode found invalid UTF-8 byte 18713 { 18714 switch (error_handler) 18715 { 18716 case error_handler_t::strict: 18717 { 18718 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr)); 18719 } 18720 18721 case error_handler_t::ignore: 18722 case error_handler_t::replace: 18723 { 18724 // in case we saw this character the first time, we 18725 // would like to read it again, because the byte 18726 // may be OK for itself, but just not OK for the 18727 // previous sequence 18728 if (undumped_chars > 0) 18729 { 18730 --i; 18731 } 18732 18733 // reset length buffer to the last accepted index; 18734 // thus removing/ignoring the invalid characters 18735 bytes = bytes_after_last_accept; 18736 18737 if (error_handler == error_handler_t::replace) 18738 { 18739 // add a replacement character 18740 if (ensure_ascii) 18741 { 18742 string_buffer[bytes++] = '\\'; 18743 string_buffer[bytes++] = 'u'; 18744 string_buffer[bytes++] = 'f'; 18745 string_buffer[bytes++] = 'f'; 18746 string_buffer[bytes++] = 'f'; 18747 string_buffer[bytes++] = 'd'; 18748 } 18749 else 18750 { 18751 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF'); 18752 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF'); 18753 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD'); 18754 } 18755 18756 // write buffer and reset index; there must be 13 bytes 18757 // left, as this is the maximal number of bytes to be 18758 // written ("\uxxxx\uxxxx\0") for one code point 18759 if (string_buffer.size() - bytes < 13) 18760 { 18761 o->write_characters(string_buffer.data(), bytes); 18762 bytes = 0; 18763 } 18764 18765 bytes_after_last_accept = bytes; 18766 } 18767 18768 undumped_chars = 0; 18769 18770 // continue processing the string 18771 state = UTF8_ACCEPT; 18772 break; 18773 } 18774 18775 default: // LCOV_EXCL_LINE 18776 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 18777 } 18778 break; 18779 } 18780 18781 default: // decode found yet incomplete multi-byte code point 18782 { 18783 if (!ensure_ascii) 18784 { 18785 // code point will not be escaped - copy byte to buffer 18786 string_buffer[bytes++] = s[i]; 18787 } 18788 ++undumped_chars; 18789 break; 18790 } 18791 } 18792 } 18793 18794 // we finished processing the string 18795 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT)) 18796 { 18797 // write buffer 18798 if (bytes > 0) 18799 { 18800 o->write_characters(string_buffer.data(), bytes); 18801 } 18802 } 18803 else 18804 { 18805 // we finish reading, but do not accept: string was incomplete 18806 switch (error_handler) 18807 { 18808 case error_handler_t::strict: 18809 { 18810 JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr)); 18811 } 18812 18813 case error_handler_t::ignore: 18814 { 18815 // write all accepted bytes 18816 o->write_characters(string_buffer.data(), bytes_after_last_accept); 18817 break; 18818 } 18819 18820 case error_handler_t::replace: 18821 { 18822 // write all accepted bytes 18823 o->write_characters(string_buffer.data(), bytes_after_last_accept); 18824 // add a replacement character 18825 if (ensure_ascii) 18826 { 18827 o->write_characters("\\ufffd", 6); 18828 } 18829 else 18830 { 18831 o->write_characters("\xEF\xBF\xBD", 3); 18832 } 18833 break; 18834 } 18835 18836 default: // LCOV_EXCL_LINE 18837 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 18838 } 18839 } 18840 } 18841 18842 private: 18843 /*! 18844 @brief count digits 18845 18846 Count the number of decimal (base 10) digits for an input unsigned integer. 18847 18848 @param[in] x unsigned integer number to count its digits 18849 @return number of decimal digits 18850 */ 18851 unsigned int count_digits(number_unsigned_t x) noexcept 18852 { 18853 unsigned int n_digits = 1; 18854 for (;;) 18855 { 18856 if (x < 10) 18857 { 18858 return n_digits; 18859 } 18860 if (x < 100) 18861 { 18862 return n_digits + 1; 18863 } 18864 if (x < 1000) 18865 { 18866 return n_digits + 2; 18867 } 18868 if (x < 10000) 18869 { 18870 return n_digits + 3; 18871 } 18872 x = x / 10000u; 18873 n_digits += 4; 18874 } 18875 } 18876 18877 /*! 18878 * @brief convert a byte to a uppercase hex representation 18879 * @param[in] byte byte to represent 18880 * @return representation ("00".."FF") 18881 */ 18882 static std::string hex_bytes(std::uint8_t byte) 18883 { 18884 std::string result = "FF"; 18885 constexpr const char* nibble_to_hex = "0123456789ABCDEF"; 18886 result[0] = nibble_to_hex[byte / 16]; 18887 result[1] = nibble_to_hex[byte % 16]; 18888 return result; 18889 } 18890 18891 // templates to avoid warnings about useless casts 18892 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0> 18893 bool is_negative_number(NumberType x) 18894 { 18895 return x < 0; 18896 } 18897 18898 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 > 18899 bool is_negative_number(NumberType /*unused*/) 18900 { 18901 return false; 18902 } 18903 18904 /*! 18905 @brief dump an integer 18906 18907 Dump a given integer to output stream @a o. Works internally with 18908 @a number_buffer. 18909 18910 @param[in] x integer number (signed or unsigned) to dump 18911 @tparam NumberType either @a number_integer_t or @a number_unsigned_t 18912 */ 18913 template < typename NumberType, detail::enable_if_t < 18914 std::is_integral<NumberType>::value || 18915 std::is_same<NumberType, number_unsigned_t>::value || 18916 std::is_same<NumberType, number_integer_t>::value || 18917 std::is_same<NumberType, binary_char_t>::value, 18918 int > = 0 > 18919 void dump_integer(NumberType x) 18920 { 18921 static constexpr std::array<std::array<char, 2>, 100> digits_to_99 18922 { 18923 { 18924 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}}, 18925 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}}, 18926 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}}, 18927 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}}, 18928 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}}, 18929 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}}, 18930 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}}, 18931 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}}, 18932 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}}, 18933 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}}, 18934 } 18935 }; 18936 18937 // special case for "0" 18938 if (x == 0) 18939 { 18940 o->write_character('0'); 18941 return; 18942 } 18943 18944 // use a pointer to fill the buffer 18945 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg) 18946 18947 number_unsigned_t abs_value; 18948 18949 unsigned int n_chars{}; 18950 18951 if (is_negative_number(x)) 18952 { 18953 *buffer_ptr = '-'; 18954 abs_value = remove_sign(static_cast<number_integer_t>(x)); 18955 18956 // account one more byte for the minus sign 18957 n_chars = 1 + count_digits(abs_value); 18958 } 18959 else 18960 { 18961 abs_value = static_cast<number_unsigned_t>(x); 18962 n_chars = count_digits(abs_value); 18963 } 18964 18965 // spare 1 byte for '\0' 18966 JSON_ASSERT(n_chars < number_buffer.size() - 1); 18967 18968 // jump to the end to generate the string from backward, 18969 // so we later avoid reversing the result 18970 buffer_ptr += n_chars; 18971 18972 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu 18973 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg 18974 while (abs_value >= 100) 18975 { 18976 const auto digits_index = static_cast<unsigned>((abs_value % 100)); 18977 abs_value /= 100; 18978 *(--buffer_ptr) = digits_to_99[digits_index][1]; 18979 *(--buffer_ptr) = digits_to_99[digits_index][0]; 18980 } 18981 18982 if (abs_value >= 10) 18983 { 18984 const auto digits_index = static_cast<unsigned>(abs_value); 18985 *(--buffer_ptr) = digits_to_99[digits_index][1]; 18986 *(--buffer_ptr) = digits_to_99[digits_index][0]; 18987 } 18988 else 18989 { 18990 *(--buffer_ptr) = static_cast<char>('0' + abs_value); 18991 } 18992 18993 o->write_characters(number_buffer.data(), n_chars); 18994 } 18995 18996 /*! 18997 @brief dump a floating-point number 18998 18999 Dump a given floating-point number to output stream @a o. Works internally 19000 with @a number_buffer. 19001 19002 @param[in] x floating-point number to dump 19003 */ 19004 void dump_float(number_float_t x) 19005 { 19006 // NaN / inf 19007 if (!std::isfinite(x)) 19008 { 19009 o->write_characters("null", 4); 19010 return; 19011 } 19012 19013 // If number_float_t is an IEEE-754 single or double precision number, 19014 // use the Grisu2 algorithm to produce short numbers which are 19015 // guaranteed to round-trip, using strtof and strtod, resp. 19016 // 19017 // NB: The test below works if <long double> == <double>. 19018 static constexpr bool is_ieee_single_or_double 19019 = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) || 19020 (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024); 19021 19022 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>()); 19023 } 19024 19025 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/) 19026 { 19027 auto* begin = number_buffer.data(); 19028 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x); 19029 19030 o->write_characters(begin, static_cast<size_t>(end - begin)); 19031 } 19032 19033 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) 19034 { 19035 // get number of digits for a float -> text -> float round-trip 19036 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10; 19037 19038 // the actual conversion 19039 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 19040 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x); 19041 19042 // negative value indicates an error 19043 JSON_ASSERT(len > 0); 19044 // check if buffer was large enough 19045 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size()); 19046 19047 // erase thousands separator 19048 if (thousands_sep != '\0') 19049 { 19050 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081 19051 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep); 19052 std::fill(end, number_buffer.end(), '\0'); 19053 JSON_ASSERT((end - number_buffer.begin()) <= len); 19054 len = (end - number_buffer.begin()); 19055 } 19056 19057 // convert decimal point to '.' 19058 if (decimal_point != '\0' && decimal_point != '.') 19059 { 19060 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081 19061 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point); 19062 if (dec_pos != number_buffer.end()) 19063 { 19064 *dec_pos = '.'; 19065 } 19066 } 19067 19068 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len)); 19069 19070 // determine if we need to append ".0" 19071 const bool value_is_int_like = 19072 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, 19073 [](char c) 19074 { 19075 return c == '.' || c == 'e'; 19076 }); 19077 19078 if (value_is_int_like) 19079 { 19080 o->write_characters(".0", 2); 19081 } 19082 } 19083 19084 /*! 19085 @brief check whether a string is UTF-8 encoded 19086 19087 The function checks each byte of a string whether it is UTF-8 encoded. The 19088 result of the check is stored in the @a state parameter. The function must 19089 be called initially with state 0 (accept). State 1 means the string must 19090 be rejected, because the current byte is not allowed. If the string is 19091 completely processed, but the state is non-zero, the string ended 19092 prematurely; that is, the last byte indicated more bytes should have 19093 followed. 19094 19095 @param[in,out] state the state of the decoding 19096 @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT) 19097 @param[in] byte next byte to decode 19098 @return new state 19099 19100 @note The function has been edited: a std::array is used. 19101 19102 @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de> 19103 @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ 19104 */ 19105 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept 19106 { 19107 static const std::array<std::uint8_t, 400> utf8d = 19108 { 19109 { 19110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F 19111 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F 19112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F 19113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F 19114 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F 19115 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF 19116 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF 19117 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF 19118 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF 19119 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 19120 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2 19121 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4 19122 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6 19123 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8 19124 } 19125 }; 19126 19127 JSON_ASSERT(byte < utf8d.size()); 19128 const std::uint8_t type = utf8d[byte]; 19129 19130 codep = (state != UTF8_ACCEPT) 19131 ? (byte & 0x3fu) | (codep << 6u) 19132 : (0xFFu >> type) & (byte); 19133 19134 const std::size_t index = 256u + (static_cast<size_t>(state) * 16u) + static_cast<size_t>(type); 19135 JSON_ASSERT(index < utf8d.size()); 19136 state = utf8d[index]; 19137 return state; 19138 } 19139 19140 /* 19141 * Overload to make the compiler happy while it is instantiating 19142 * dump_integer for number_unsigned_t. 19143 * Must never be called. 19144 */ 19145 number_unsigned_t remove_sign(number_unsigned_t x) 19146 { 19147 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 19148 return x; // LCOV_EXCL_LINE 19149 } 19150 19151 /* 19152 * Helper function for dump_integer 19153 * 19154 * This function takes a negative signed integer and returns its absolute 19155 * value as unsigned integer. The plus/minus shuffling is necessary as we can 19156 * not directly remove the sign of an arbitrary signed integer as the 19157 * absolute values of INT_MIN and INT_MAX are usually not the same. See 19158 * #1708 for details. 19159 */ 19160 number_unsigned_t remove_sign(number_integer_t x) noexcept 19161 { 19162 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression) 19163 return static_cast<number_unsigned_t>(-(x + 1)) + 1; 19164 } 19165 19166 private: 19167 /// the output of the serializer 19168 output_adapter_t<char> o = nullptr; 19169 19170 /// a (hopefully) large enough character buffer 19171 std::array<char, 64> number_buffer{{}}; 19172 19173 /// the locale 19174 const std::lconv* loc = nullptr; 19175 /// the locale's thousand separator character 19176 const char thousands_sep = '\0'; 19177 /// the locale's decimal point character 19178 const char decimal_point = '\0'; 19179 19180 /// string buffer 19181 std::array<char, 512> string_buffer{{}}; 19182 19183 /// the indentation character 19184 const char indent_char; 19185 /// the indentation string 19186 string_t indent_string; 19187 19188 /// error_handler how to react on decoding errors 19189 const error_handler_t error_handler; 19190 }; 19191 19192 } // namespace detail 19193 NLOHMANN_JSON_NAMESPACE_END 19194 19195 // #include <nlohmann/detail/value_t.hpp> 19196 19197 // #include <nlohmann/json_fwd.hpp> 19198 19199 // #include <nlohmann/ordered_map.hpp> 19200 // __ _____ _____ _____ 19201 // __| | __| | | | JSON for Modern C++ 19202 // | | |__ | | | | | | version 3.11.3 19203 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 19204 // 19205 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 19206 // SPDX-License-Identifier: MIT 19207 19208 19209 19210 #include <functional> // equal_to, less 19211 #include <initializer_list> // initializer_list 19212 #include <iterator> // input_iterator_tag, iterator_traits 19213 #include <memory> // allocator 19214 #include <stdexcept> // for out_of_range 19215 #include <type_traits> // enable_if, is_convertible 19216 #include <utility> // pair 19217 #include <vector> // vector 19218 19219 // #include <nlohmann/detail/macro_scope.hpp> 19220 19221 // #include <nlohmann/detail/meta/type_traits.hpp> 19222 19223 19224 NLOHMANN_JSON_NAMESPACE_BEGIN 19225 19226 /// ordered_map: a minimal map-like container that preserves insertion order 19227 /// for use within nlohmann::basic_json<ordered_map> 19228 template <class Key, class T, class IgnoredLess = std::less<Key>, 19229 class Allocator = std::allocator<std::pair<const Key, T>>> 19230 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator> 19231 { 19232 using key_type = Key; 19233 using mapped_type = T; 19234 using Container = std::vector<std::pair<const Key, T>, Allocator>; 19235 using iterator = typename Container::iterator; 19236 using const_iterator = typename Container::const_iterator; 19237 using size_type = typename Container::size_type; 19238 using value_type = typename Container::value_type; 19239 #ifdef JSON_HAS_CPP_14 19240 using key_compare = std::equal_to<>; 19241 #else 19242 using key_compare = std::equal_to<Key>; 19243 #endif 19244 19245 // Explicit constructors instead of `using Container::Container` 19246 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4) 19247 ordered_map() noexcept(noexcept(Container())) : Container{} {} 19248 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {} 19249 template <class It> 19250 ordered_map(It first, It last, const Allocator& alloc = Allocator()) 19251 : Container{first, last, alloc} {} 19252 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() ) 19253 : Container{init, alloc} {} 19254 19255 std::pair<iterator, bool> emplace(const key_type& key, T&& t) 19256 { 19257 for (auto it = this->begin(); it != this->end(); ++it) 19258 { 19259 if (m_compare(it->first, key)) 19260 { 19261 return {it, false}; 19262 } 19263 } 19264 Container::emplace_back(key, std::forward<T>(t)); 19265 return {std::prev(this->end()), true}; 19266 } 19267 19268 template<class KeyType, detail::enable_if_t< 19269 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19270 std::pair<iterator, bool> emplace(KeyType && key, T && t) 19271 { 19272 for (auto it = this->begin(); it != this->end(); ++it) 19273 { 19274 if (m_compare(it->first, key)) 19275 { 19276 return {it, false}; 19277 } 19278 } 19279 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t)); 19280 return {std::prev(this->end()), true}; 19281 } 19282 19283 T& operator[](const key_type& key) 19284 { 19285 return emplace(key, T{}).first->second; 19286 } 19287 19288 template<class KeyType, detail::enable_if_t< 19289 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19290 T & operator[](KeyType && key) 19291 { 19292 return emplace(std::forward<KeyType>(key), T{}).first->second; 19293 } 19294 19295 const T& operator[](const key_type& key) const 19296 { 19297 return at(key); 19298 } 19299 19300 template<class KeyType, detail::enable_if_t< 19301 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19302 const T & operator[](KeyType && key) const 19303 { 19304 return at(std::forward<KeyType>(key)); 19305 } 19306 19307 T& at(const key_type& key) 19308 { 19309 for (auto it = this->begin(); it != this->end(); ++it) 19310 { 19311 if (m_compare(it->first, key)) 19312 { 19313 return it->second; 19314 } 19315 } 19316 19317 JSON_THROW(std::out_of_range("key not found")); 19318 } 19319 19320 template<class KeyType, detail::enable_if_t< 19321 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19322 T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) 19323 { 19324 for (auto it = this->begin(); it != this->end(); ++it) 19325 { 19326 if (m_compare(it->first, key)) 19327 { 19328 return it->second; 19329 } 19330 } 19331 19332 JSON_THROW(std::out_of_range("key not found")); 19333 } 19334 19335 const T& at(const key_type& key) const 19336 { 19337 for (auto it = this->begin(); it != this->end(); ++it) 19338 { 19339 if (m_compare(it->first, key)) 19340 { 19341 return it->second; 19342 } 19343 } 19344 19345 JSON_THROW(std::out_of_range("key not found")); 19346 } 19347 19348 template<class KeyType, detail::enable_if_t< 19349 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19350 const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) 19351 { 19352 for (auto it = this->begin(); it != this->end(); ++it) 19353 { 19354 if (m_compare(it->first, key)) 19355 { 19356 return it->second; 19357 } 19358 } 19359 19360 JSON_THROW(std::out_of_range("key not found")); 19361 } 19362 19363 size_type erase(const key_type& key) 19364 { 19365 for (auto it = this->begin(); it != this->end(); ++it) 19366 { 19367 if (m_compare(it->first, key)) 19368 { 19369 // Since we cannot move const Keys, re-construct them in place 19370 for (auto next = it; ++next != this->end(); ++it) 19371 { 19372 it->~value_type(); // Destroy but keep allocation 19373 new (&*it) value_type{std::move(*next)}; 19374 } 19375 Container::pop_back(); 19376 return 1; 19377 } 19378 } 19379 return 0; 19380 } 19381 19382 template<class KeyType, detail::enable_if_t< 19383 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19384 size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) 19385 { 19386 for (auto it = this->begin(); it != this->end(); ++it) 19387 { 19388 if (m_compare(it->first, key)) 19389 { 19390 // Since we cannot move const Keys, re-construct them in place 19391 for (auto next = it; ++next != this->end(); ++it) 19392 { 19393 it->~value_type(); // Destroy but keep allocation 19394 new (&*it) value_type{std::move(*next)}; 19395 } 19396 Container::pop_back(); 19397 return 1; 19398 } 19399 } 19400 return 0; 19401 } 19402 19403 iterator erase(iterator pos) 19404 { 19405 return erase(pos, std::next(pos)); 19406 } 19407 19408 iterator erase(iterator first, iterator last) 19409 { 19410 if (first == last) 19411 { 19412 return first; 19413 } 19414 19415 const auto elements_affected = std::distance(first, last); 19416 const auto offset = std::distance(Container::begin(), first); 19417 19418 // This is the start situation. We need to delete elements_affected 19419 // elements (3 in this example: e, f, g), and need to return an 19420 // iterator past the last deleted element (h in this example). 19421 // Note that offset is the distance from the start of the vector 19422 // to first. We will need this later. 19423 19424 // [ a, b, c, d, e, f, g, h, i, j ] 19425 // ^ ^ 19426 // first last 19427 19428 // Since we cannot move const Keys, we re-construct them in place. 19429 // We start at first and re-construct (viz. copy) the elements from 19430 // the back of the vector. Example for first iteration: 19431 19432 // ,--------. 19433 // v | destroy e and re-construct with h 19434 // [ a, b, c, d, e, f, g, h, i, j ] 19435 // ^ ^ 19436 // it it + elements_affected 19437 19438 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it) 19439 { 19440 it->~value_type(); // destroy but keep allocation 19441 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it 19442 } 19443 19444 // [ a, b, c, d, h, i, j, h, i, j ] 19445 // ^ ^ 19446 // first last 19447 19448 // remove the unneeded elements at the end of the vector 19449 Container::resize(this->size() - static_cast<size_type>(elements_affected)); 19450 19451 // [ a, b, c, d, h, i, j ] 19452 // ^ ^ 19453 // first last 19454 19455 // first is now pointing past the last deleted element, but we cannot 19456 // use this iterator, because it may have been invalidated by the 19457 // resize call. Instead, we can return begin() + offset. 19458 return Container::begin() + offset; 19459 } 19460 19461 size_type count(const key_type& key) const 19462 { 19463 for (auto it = this->begin(); it != this->end(); ++it) 19464 { 19465 if (m_compare(it->first, key)) 19466 { 19467 return 1; 19468 } 19469 } 19470 return 0; 19471 } 19472 19473 template<class KeyType, detail::enable_if_t< 19474 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19475 size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) 19476 { 19477 for (auto it = this->begin(); it != this->end(); ++it) 19478 { 19479 if (m_compare(it->first, key)) 19480 { 19481 return 1; 19482 } 19483 } 19484 return 0; 19485 } 19486 19487 iterator find(const key_type& key) 19488 { 19489 for (auto it = this->begin(); it != this->end(); ++it) 19490 { 19491 if (m_compare(it->first, key)) 19492 { 19493 return it; 19494 } 19495 } 19496 return Container::end(); 19497 } 19498 19499 template<class KeyType, detail::enable_if_t< 19500 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19501 iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) 19502 { 19503 for (auto it = this->begin(); it != this->end(); ++it) 19504 { 19505 if (m_compare(it->first, key)) 19506 { 19507 return it; 19508 } 19509 } 19510 return Container::end(); 19511 } 19512 19513 const_iterator find(const key_type& key) const 19514 { 19515 for (auto it = this->begin(); it != this->end(); ++it) 19516 { 19517 if (m_compare(it->first, key)) 19518 { 19519 return it; 19520 } 19521 } 19522 return Container::end(); 19523 } 19524 19525 std::pair<iterator, bool> insert( value_type&& value ) 19526 { 19527 return emplace(value.first, std::move(value.second)); 19528 } 19529 19530 std::pair<iterator, bool> insert( const value_type& value ) 19531 { 19532 for (auto it = this->begin(); it != this->end(); ++it) 19533 { 19534 if (m_compare(it->first, value.first)) 19535 { 19536 return {it, false}; 19537 } 19538 } 19539 Container::push_back(value); 19540 return {--this->end(), true}; 19541 } 19542 19543 template<typename InputIt> 19544 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category, 19545 std::input_iterator_tag>::value>::type; 19546 19547 template<typename InputIt, typename = require_input_iter<InputIt>> 19548 void insert(InputIt first, InputIt last) 19549 { 19550 for (auto it = first; it != last; ++it) 19551 { 19552 insert(*it); 19553 } 19554 } 19555 19556 private: 19557 JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare(); 19558 }; 19559 19560 NLOHMANN_JSON_NAMESPACE_END 19561 19562 19563 #if defined(JSON_HAS_CPP_17) 19564 #if JSON_HAS_STATIC_RTTI 19565 #include <any> 19566 #endif 19567 #include <string_view> 19568 #endif 19569 19570 /*! 19571 @brief namespace for Niels Lohmann 19572 @see https://github.com/nlohmann 19573 @since version 1.0.0 19574 */ 19575 NLOHMANN_JSON_NAMESPACE_BEGIN 19576 19577 /*! 19578 @brief a class to store JSON values 19579 19580 @internal 19581 @invariant The member variables @a m_value and @a m_type have the following 19582 relationship: 19583 - If `m_type == value_t::object`, then `m_value.object != nullptr`. 19584 - If `m_type == value_t::array`, then `m_value.array != nullptr`. 19585 - If `m_type == value_t::string`, then `m_value.string != nullptr`. 19586 The invariants are checked by member function assert_invariant(). 19587 19588 @note ObjectType trick from https://stackoverflow.com/a/9860911 19589 @endinternal 19590 19591 @since version 1.0.0 19592 19593 @nosubgrouping 19594 */ 19595 NLOHMANN_BASIC_JSON_TPL_DECLARATION 19596 class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) 19597 : public ::nlohmann::detail::json_base_class<CustomBaseClass> 19598 { 19599 private: 19600 template<detail::value_t> friend struct detail::external_constructor; 19601 19602 template<typename> 19603 friend class ::nlohmann::json_pointer; 19604 // can be restored when json_pointer backwards compatibility is removed 19605 // friend ::nlohmann::json_pointer<StringType>; 19606 19607 template<typename BasicJsonType, typename InputType> 19608 friend class ::nlohmann::detail::parser; 19609 friend ::nlohmann::detail::serializer<basic_json>; 19610 template<typename BasicJsonType> 19611 friend class ::nlohmann::detail::iter_impl; 19612 template<typename BasicJsonType, typename CharType> 19613 friend class ::nlohmann::detail::binary_writer; 19614 template<typename BasicJsonType, typename InputType, typename SAX> 19615 friend class ::nlohmann::detail::binary_reader; 19616 template<typename BasicJsonType> 19617 friend class ::nlohmann::detail::json_sax_dom_parser; 19618 template<typename BasicJsonType> 19619 friend class ::nlohmann::detail::json_sax_dom_callback_parser; 19620 friend class ::nlohmann::detail::exception; 19621 19622 /// workaround type for MSVC 19623 using basic_json_t = NLOHMANN_BASIC_JSON_TPL; 19624 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>; 19625 19626 JSON_PRIVATE_UNLESS_TESTED: 19627 // convenience aliases for types residing in namespace detail; 19628 using lexer = ::nlohmann::detail::lexer_base<basic_json>; 19629 19630 template<typename InputAdapterType> 19631 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser( 19632 InputAdapterType adapter, 19633 detail::parser_callback_t<basic_json>cb = nullptr, 19634 const bool allow_exceptions = true, 19635 const bool ignore_comments = false 19636 ) 19637 { 19638 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter), 19639 std::move(cb), allow_exceptions, ignore_comments); 19640 } 19641 19642 private: 19643 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t; 19644 template<typename BasicJsonType> 19645 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>; 19646 template<typename BasicJsonType> 19647 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>; 19648 template<typename Iterator> 19649 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>; 19650 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>; 19651 19652 template<typename CharType> 19653 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>; 19654 19655 template<typename InputType> 19656 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>; 19657 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>; 19658 19659 JSON_PRIVATE_UNLESS_TESTED: 19660 using serializer = ::nlohmann::detail::serializer<basic_json>; 19661 19662 public: 19663 using value_t = detail::value_t; 19664 /// JSON Pointer, see @ref nlohmann::json_pointer 19665 using json_pointer = ::nlohmann::json_pointer<StringType>; 19666 template<typename T, typename SFINAE> 19667 using json_serializer = JSONSerializer<T, SFINAE>; 19668 /// how to treat decoding errors 19669 using error_handler_t = detail::error_handler_t; 19670 /// how to treat CBOR tags 19671 using cbor_tag_handler_t = detail::cbor_tag_handler_t; 19672 /// helper type for initializer lists of basic_json values 19673 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>; 19674 19675 using input_format_t = detail::input_format_t; 19676 /// SAX interface type, see @ref nlohmann::json_sax 19677 using json_sax_t = json_sax<basic_json>; 19678 19679 //////////////// 19680 // exceptions // 19681 //////////////// 19682 19683 /// @name exceptions 19684 /// Classes to implement user-defined exceptions. 19685 /// @{ 19686 19687 using exception = detail::exception; 19688 using parse_error = detail::parse_error; 19689 using invalid_iterator = detail::invalid_iterator; 19690 using type_error = detail::type_error; 19691 using out_of_range = detail::out_of_range; 19692 using other_error = detail::other_error; 19693 19694 /// @} 19695 19696 ///////////////////// 19697 // container types // 19698 ///////////////////// 19699 19700 /// @name container types 19701 /// The canonic container types to use @ref basic_json like any other STL 19702 /// container. 19703 /// @{ 19704 19705 /// the type of elements in a basic_json container 19706 using value_type = basic_json; 19707 19708 /// the type of an element reference 19709 using reference = value_type&; 19710 /// the type of an element const reference 19711 using const_reference = const value_type&; 19712 19713 /// a type to represent differences between iterators 19714 using difference_type = std::ptrdiff_t; 19715 /// a type to represent container sizes 19716 using size_type = std::size_t; 19717 19718 /// the allocator type 19719 using allocator_type = AllocatorType<basic_json>; 19720 19721 /// the type of an element pointer 19722 using pointer = typename std::allocator_traits<allocator_type>::pointer; 19723 /// the type of an element const pointer 19724 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer; 19725 19726 /// an iterator for a basic_json container 19727 using iterator = iter_impl<basic_json>; 19728 /// a const iterator for a basic_json container 19729 using const_iterator = iter_impl<const basic_json>; 19730 /// a reverse iterator for a basic_json container 19731 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>; 19732 /// a const reverse iterator for a basic_json container 19733 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>; 19734 19735 /// @} 19736 19737 /// @brief returns the allocator associated with the container 19738 /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/ 19739 static allocator_type get_allocator() 19740 { 19741 return allocator_type(); 19742 } 19743 19744 /// @brief returns version information on the library 19745 /// @sa https://json.nlohmann.me/api/basic_json/meta/ 19746 JSON_HEDLEY_WARN_UNUSED_RESULT 19747 static basic_json meta() 19748 { 19749 basic_json result; 19750 19751 result["copyright"] = "(C) 2013-2023 Niels Lohmann"; 19752 result["name"] = "JSON for Modern C++"; 19753 result["url"] = "https://github.com/nlohmann/json"; 19754 result["version"]["string"] = 19755 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.', 19756 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.', 19757 std::to_string(NLOHMANN_JSON_VERSION_PATCH)); 19758 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR; 19759 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR; 19760 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH; 19761 19762 #ifdef _WIN32 19763 result["platform"] = "win32"; 19764 #elif defined __linux__ 19765 result["platform"] = "linux"; 19766 #elif defined __APPLE__ 19767 result["platform"] = "apple"; 19768 #elif defined __unix__ 19769 result["platform"] = "unix"; 19770 #else 19771 result["platform"] = "unknown"; 19772 #endif 19773 19774 #if defined(__ICC) || defined(__INTEL_COMPILER) 19775 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; 19776 #elif defined(__clang__) 19777 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; 19778 #elif defined(__GNUC__) || defined(__GNUG__) 19779 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat( 19780 std::to_string(__GNUC__), '.', 19781 std::to_string(__GNUC_MINOR__), '.', 19782 std::to_string(__GNUC_PATCHLEVEL__)) 19783 } 19784 }; 19785 #elif defined(__HP_cc) || defined(__HP_aCC) 19786 result["compiler"] = "hp" 19787 #elif defined(__IBMCPP__) 19788 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; 19789 #elif defined(_MSC_VER) 19790 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; 19791 #elif defined(__PGI) 19792 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; 19793 #elif defined(__SUNPRO_CC) 19794 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; 19795 #else 19796 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; 19797 #endif 19798 19799 #if defined(_MSVC_LANG) 19800 result["compiler"]["c++"] = std::to_string(_MSVC_LANG); 19801 #elif defined(__cplusplus) 19802 result["compiler"]["c++"] = std::to_string(__cplusplus); 19803 #else 19804 result["compiler"]["c++"] = "unknown"; 19805 #endif 19806 return result; 19807 } 19808 19809 /////////////////////////// 19810 // JSON value data types // 19811 /////////////////////////// 19812 19813 /// @name JSON value data types 19814 /// The data types to store a JSON value. These types are derived from 19815 /// the template arguments passed to class @ref basic_json. 19816 /// @{ 19817 19818 /// @brief default object key comparator type 19819 /// The actual object key comparator type (@ref object_comparator_t) may be 19820 /// different. 19821 /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/ 19822 #if defined(JSON_HAS_CPP_14) 19823 // use of transparent comparator avoids unnecessary repeated construction of temporaries 19824 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType) 19825 using default_object_comparator_t = std::less<>; 19826 #else 19827 using default_object_comparator_t = std::less<StringType>; 19828 #endif 19829 19830 /// @brief a type for an object 19831 /// @sa https://json.nlohmann.me/api/basic_json/object_t/ 19832 using object_t = ObjectType<StringType, 19833 basic_json, 19834 default_object_comparator_t, 19835 AllocatorType<std::pair<const StringType, 19836 basic_json>>>; 19837 19838 /// @brief a type for an array 19839 /// @sa https://json.nlohmann.me/api/basic_json/array_t/ 19840 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>; 19841 19842 /// @brief a type for a string 19843 /// @sa https://json.nlohmann.me/api/basic_json/string_t/ 19844 using string_t = StringType; 19845 19846 /// @brief a type for a boolean 19847 /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/ 19848 using boolean_t = BooleanType; 19849 19850 /// @brief a type for a number (integer) 19851 /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/ 19852 using number_integer_t = NumberIntegerType; 19853 19854 /// @brief a type for a number (unsigned) 19855 /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/ 19856 using number_unsigned_t = NumberUnsignedType; 19857 19858 /// @brief a type for a number (floating-point) 19859 /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/ 19860 using number_float_t = NumberFloatType; 19861 19862 /// @brief a type for a packed binary type 19863 /// @sa https://json.nlohmann.me/api/basic_json/binary_t/ 19864 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>; 19865 19866 /// @brief object key comparator type 19867 /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/ 19868 using object_comparator_t = detail::actual_object_comparator_t<basic_json>; 19869 19870 /// @} 19871 19872 private: 19873 19874 /// helper for exception-safe object creation 19875 template<typename T, typename... Args> 19876 JSON_HEDLEY_RETURNS_NON_NULL 19877 static T* create(Args&& ... args) 19878 { 19879 AllocatorType<T> alloc; 19880 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>; 19881 19882 auto deleter = [&](T * obj) 19883 { 19884 AllocatorTraits::deallocate(alloc, obj, 1); 19885 }; 19886 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter); 19887 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...); 19888 JSON_ASSERT(obj != nullptr); 19889 return obj.release(); 19890 } 19891 19892 //////////////////////// 19893 // JSON value storage // 19894 //////////////////////// 19895 19896 JSON_PRIVATE_UNLESS_TESTED: 19897 /*! 19898 @brief a JSON value 19899 19900 The actual storage for a JSON value of the @ref basic_json class. This 19901 union combines the different storage types for the JSON value types 19902 defined in @ref value_t. 19903 19904 JSON type | value_t type | used type 19905 --------- | --------------- | ------------------------ 19906 object | object | pointer to @ref object_t 19907 array | array | pointer to @ref array_t 19908 string | string | pointer to @ref string_t 19909 boolean | boolean | @ref boolean_t 19910 number | number_integer | @ref number_integer_t 19911 number | number_unsigned | @ref number_unsigned_t 19912 number | number_float | @ref number_float_t 19913 binary | binary | pointer to @ref binary_t 19914 null | null | *no value is stored* 19915 19916 @note Variable-length types (objects, arrays, and strings) are stored as 19917 pointers. The size of the union should not exceed 64 bits if the default 19918 value types are used. 19919 19920 @since version 1.0.0 19921 */ 19922 union json_value 19923 { 19924 /// object (stored with pointer to save storage) 19925 object_t* object; 19926 /// array (stored with pointer to save storage) 19927 array_t* array; 19928 /// string (stored with pointer to save storage) 19929 string_t* string; 19930 /// binary (stored with pointer to save storage) 19931 binary_t* binary; 19932 /// boolean 19933 boolean_t boolean; 19934 /// number (integer) 19935 number_integer_t number_integer; 19936 /// number (unsigned integer) 19937 number_unsigned_t number_unsigned; 19938 /// number (floating-point) 19939 number_float_t number_float; 19940 19941 /// default constructor (for null values) 19942 json_value() = default; 19943 /// constructor for booleans 19944 json_value(boolean_t v) noexcept : boolean(v) {} 19945 /// constructor for numbers (integer) 19946 json_value(number_integer_t v) noexcept : number_integer(v) {} 19947 /// constructor for numbers (unsigned) 19948 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} 19949 /// constructor for numbers (floating-point) 19950 json_value(number_float_t v) noexcept : number_float(v) {} 19951 /// constructor for empty values of a given type 19952 json_value(value_t t) 19953 { 19954 switch (t) 19955 { 19956 case value_t::object: 19957 { 19958 object = create<object_t>(); 19959 break; 19960 } 19961 19962 case value_t::array: 19963 { 19964 array = create<array_t>(); 19965 break; 19966 } 19967 19968 case value_t::string: 19969 { 19970 string = create<string_t>(""); 19971 break; 19972 } 19973 19974 case value_t::binary: 19975 { 19976 binary = create<binary_t>(); 19977 break; 19978 } 19979 19980 case value_t::boolean: 19981 { 19982 boolean = static_cast<boolean_t>(false); 19983 break; 19984 } 19985 19986 case value_t::number_integer: 19987 { 19988 number_integer = static_cast<number_integer_t>(0); 19989 break; 19990 } 19991 19992 case value_t::number_unsigned: 19993 { 19994 number_unsigned = static_cast<number_unsigned_t>(0); 19995 break; 19996 } 19997 19998 case value_t::number_float: 19999 { 20000 number_float = static_cast<number_float_t>(0.0); 20001 break; 20002 } 20003 20004 case value_t::null: 20005 { 20006 object = nullptr; // silence warning, see #821 20007 break; 20008 } 20009 20010 case value_t::discarded: 20011 default: 20012 { 20013 object = nullptr; // silence warning, see #821 20014 if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) 20015 { 20016 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE 20017 } 20018 break; 20019 } 20020 } 20021 } 20022 20023 /// constructor for strings 20024 json_value(const string_t& value) : string(create<string_t>(value)) {} 20025 20026 /// constructor for rvalue strings 20027 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {} 20028 20029 /// constructor for objects 20030 json_value(const object_t& value) : object(create<object_t>(value)) {} 20031 20032 /// constructor for rvalue objects 20033 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {} 20034 20035 /// constructor for arrays 20036 json_value(const array_t& value) : array(create<array_t>(value)) {} 20037 20038 /// constructor for rvalue arrays 20039 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {} 20040 20041 /// constructor for binary arrays 20042 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {} 20043 20044 /// constructor for rvalue binary arrays 20045 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {} 20046 20047 /// constructor for binary arrays (internal type) 20048 json_value(const binary_t& value) : binary(create<binary_t>(value)) {} 20049 20050 /// constructor for rvalue binary arrays (internal type) 20051 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {} 20052 20053 void destroy(value_t t) 20054 { 20055 if ( 20056 (t == value_t::object && object == nullptr) || 20057 (t == value_t::array && array == nullptr) || 20058 (t == value_t::string && string == nullptr) || 20059 (t == value_t::binary && binary == nullptr) 20060 ) 20061 { 20062 //not initialized (e.g. due to exception in the ctor) 20063 return; 20064 } 20065 if (t == value_t::array || t == value_t::object) 20066 { 20067 // flatten the current json_value to a heap-allocated stack 20068 std::vector<basic_json> stack; 20069 20070 // move the top-level items to stack 20071 if (t == value_t::array) 20072 { 20073 stack.reserve(array->size()); 20074 std::move(array->begin(), array->end(), std::back_inserter(stack)); 20075 } 20076 else 20077 { 20078 stack.reserve(object->size()); 20079 for (auto&& it : *object) 20080 { 20081 stack.push_back(std::move(it.second)); 20082 } 20083 } 20084 20085 while (!stack.empty()) 20086 { 20087 // move the last item to local variable to be processed 20088 basic_json current_item(std::move(stack.back())); 20089 stack.pop_back(); 20090 20091 // if current_item is array/object, move 20092 // its children to the stack to be processed later 20093 if (current_item.is_array()) 20094 { 20095 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack)); 20096 20097 current_item.m_data.m_value.array->clear(); 20098 } 20099 else if (current_item.is_object()) 20100 { 20101 for (auto&& it : *current_item.m_data.m_value.object) 20102 { 20103 stack.push_back(std::move(it.second)); 20104 } 20105 20106 current_item.m_data.m_value.object->clear(); 20107 } 20108 20109 // it's now safe that current_item get destructed 20110 // since it doesn't have any children 20111 } 20112 } 20113 20114 switch (t) 20115 { 20116 case value_t::object: 20117 { 20118 AllocatorType<object_t> alloc; 20119 std::allocator_traits<decltype(alloc)>::destroy(alloc, object); 20120 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1); 20121 break; 20122 } 20123 20124 case value_t::array: 20125 { 20126 AllocatorType<array_t> alloc; 20127 std::allocator_traits<decltype(alloc)>::destroy(alloc, array); 20128 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1); 20129 break; 20130 } 20131 20132 case value_t::string: 20133 { 20134 AllocatorType<string_t> alloc; 20135 std::allocator_traits<decltype(alloc)>::destroy(alloc, string); 20136 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1); 20137 break; 20138 } 20139 20140 case value_t::binary: 20141 { 20142 AllocatorType<binary_t> alloc; 20143 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary); 20144 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1); 20145 break; 20146 } 20147 20148 case value_t::null: 20149 case value_t::boolean: 20150 case value_t::number_integer: 20151 case value_t::number_unsigned: 20152 case value_t::number_float: 20153 case value_t::discarded: 20154 default: 20155 { 20156 break; 20157 } 20158 } 20159 } 20160 }; 20161 20162 private: 20163 /*! 20164 @brief checks the class invariants 20165 20166 This function asserts the class invariants. It needs to be called at the 20167 end of every constructor to make sure that created objects respect the 20168 invariant. Furthermore, it has to be called each time the type of a JSON 20169 value is changed, because the invariant expresses a relationship between 20170 @a m_type and @a m_value. 20171 20172 Furthermore, the parent relation is checked for arrays and objects: If 20173 @a check_parents true and the value is an array or object, then the 20174 container's elements must have the current value as parent. 20175 20176 @param[in] check_parents whether the parent relation should be checked. 20177 The value is true by default and should only be set to false 20178 during destruction of objects when the invariant does not 20179 need to hold. 20180 */ 20181 void assert_invariant(bool check_parents = true) const noexcept 20182 { 20183 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr); 20184 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr); 20185 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr); 20186 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr); 20187 20188 #if JSON_DIAGNOSTICS 20189 JSON_TRY 20190 { 20191 // cppcheck-suppress assertWithSideEffect 20192 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j) 20193 { 20194 return j.m_parent == this; 20195 })); 20196 } 20197 JSON_CATCH(...) {} // LCOV_EXCL_LINE 20198 #endif 20199 static_cast<void>(check_parents); 20200 } 20201 20202 void set_parents() 20203 { 20204 #if JSON_DIAGNOSTICS 20205 switch (m_data.m_type) 20206 { 20207 case value_t::array: 20208 { 20209 for (auto& element : *m_data.m_value.array) 20210 { 20211 element.m_parent = this; 20212 } 20213 break; 20214 } 20215 20216 case value_t::object: 20217 { 20218 for (auto& element : *m_data.m_value.object) 20219 { 20220 element.second.m_parent = this; 20221 } 20222 break; 20223 } 20224 20225 case value_t::null: 20226 case value_t::string: 20227 case value_t::boolean: 20228 case value_t::number_integer: 20229 case value_t::number_unsigned: 20230 case value_t::number_float: 20231 case value_t::binary: 20232 case value_t::discarded: 20233 default: 20234 break; 20235 } 20236 #endif 20237 } 20238 20239 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents) 20240 { 20241 #if JSON_DIAGNOSTICS 20242 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i) 20243 { 20244 (it + i)->m_parent = this; 20245 } 20246 #else 20247 static_cast<void>(count_set_parents); 20248 #endif 20249 return it; 20250 } 20251 20252 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1)) 20253 { 20254 #if JSON_DIAGNOSTICS 20255 if (old_capacity != static_cast<std::size_t>(-1)) 20256 { 20257 // see https://github.com/nlohmann/json/issues/2838 20258 JSON_ASSERT(type() == value_t::array); 20259 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) 20260 { 20261 // capacity has changed: update all parents 20262 set_parents(); 20263 return j; 20264 } 20265 } 20266 20267 // ordered_json uses a vector internally, so pointers could have 20268 // been invalidated; see https://github.com/nlohmann/json/issues/2962 20269 #ifdef JSON_HEDLEY_MSVC_VERSION 20270 #pragma warning(push ) 20271 #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr 20272 #endif 20273 if (detail::is_ordered_map<object_t>::value) 20274 { 20275 set_parents(); 20276 return j; 20277 } 20278 #ifdef JSON_HEDLEY_MSVC_VERSION 20279 #pragma warning( pop ) 20280 #endif 20281 20282 j.m_parent = this; 20283 #else 20284 static_cast<void>(j); 20285 static_cast<void>(old_capacity); 20286 #endif 20287 return j; 20288 } 20289 20290 public: 20291 ////////////////////////// 20292 // JSON parser callback // 20293 ////////////////////////// 20294 20295 /// @brief parser event types 20296 /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/ 20297 using parse_event_t = detail::parse_event_t; 20298 20299 /// @brief per-element parser callback type 20300 /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/ 20301 using parser_callback_t = detail::parser_callback_t<basic_json>; 20302 20303 ////////////////// 20304 // constructors // 20305 ////////////////// 20306 20307 /// @name constructors and destructors 20308 /// Constructors of class @ref basic_json, copy/move constructor, copy 20309 /// assignment, static functions creating objects, and the destructor. 20310 /// @{ 20311 20312 /// @brief create an empty value with a given type 20313 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20314 basic_json(const value_t v) 20315 : m_data(v) 20316 { 20317 assert_invariant(); 20318 } 20319 20320 /// @brief create a null object 20321 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20322 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape) 20323 : basic_json(value_t::null) 20324 { 20325 assert_invariant(); 20326 } 20327 20328 /// @brief create a JSON value from compatible types 20329 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20330 template < typename CompatibleType, 20331 typename U = detail::uncvref_t<CompatibleType>, 20332 detail::enable_if_t < 20333 !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 > 20334 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape) 20335 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(), 20336 std::forward<CompatibleType>(val)))) 20337 { 20338 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val)); 20339 set_parents(); 20340 assert_invariant(); 20341 } 20342 20343 /// @brief create a JSON value from an existing one 20344 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20345 template < typename BasicJsonType, 20346 detail::enable_if_t < 20347 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 > 20348 basic_json(const BasicJsonType& val) 20349 { 20350 using other_boolean_t = typename BasicJsonType::boolean_t; 20351 using other_number_float_t = typename BasicJsonType::number_float_t; 20352 using other_number_integer_t = typename BasicJsonType::number_integer_t; 20353 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t; 20354 using other_string_t = typename BasicJsonType::string_t; 20355 using other_object_t = typename BasicJsonType::object_t; 20356 using other_array_t = typename BasicJsonType::array_t; 20357 using other_binary_t = typename BasicJsonType::binary_t; 20358 20359 switch (val.type()) 20360 { 20361 case value_t::boolean: 20362 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>()); 20363 break; 20364 case value_t::number_float: 20365 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>()); 20366 break; 20367 case value_t::number_integer: 20368 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>()); 20369 break; 20370 case value_t::number_unsigned: 20371 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>()); 20372 break; 20373 case value_t::string: 20374 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>()); 20375 break; 20376 case value_t::object: 20377 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>()); 20378 break; 20379 case value_t::array: 20380 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>()); 20381 break; 20382 case value_t::binary: 20383 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>()); 20384 break; 20385 case value_t::null: 20386 *this = nullptr; 20387 break; 20388 case value_t::discarded: 20389 m_data.m_type = value_t::discarded; 20390 break; 20391 default: // LCOV_EXCL_LINE 20392 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 20393 } 20394 JSON_ASSERT(m_data.m_type == val.type()); 20395 set_parents(); 20396 assert_invariant(); 20397 } 20398 20399 /// @brief create a container (array or object) from an initializer list 20400 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20401 basic_json(initializer_list_t init, 20402 bool type_deduction = true, 20403 value_t manual_type = value_t::array) 20404 { 20405 // check if each element is an array with two elements whose first 20406 // element is a string 20407 bool is_an_object = std::all_of(init.begin(), init.end(), 20408 [](const detail::json_ref<basic_json>& element_ref) 20409 { 20410 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int; 20411 // (many string types can be constructed from 0 via its null-pointer guise, so we get a 20412 // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows) 20413 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string(); 20414 }); 20415 20416 // adjust type if type deduction is not wanted 20417 if (!type_deduction) 20418 { 20419 // if array is wanted, do not create an object though possible 20420 if (manual_type == value_t::array) 20421 { 20422 is_an_object = false; 20423 } 20424 20425 // if object is wanted but impossible, throw an exception 20426 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) 20427 { 20428 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr)); 20429 } 20430 } 20431 20432 if (is_an_object) 20433 { 20434 // the initializer list is a list of pairs -> create object 20435 m_data.m_type = value_t::object; 20436 m_data.m_value = value_t::object; 20437 20438 for (auto& element_ref : init) 20439 { 20440 auto element = element_ref.moved_or_copied(); 20441 m_data.m_value.object->emplace( 20442 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)), 20443 std::move((*element.m_data.m_value.array)[1])); 20444 } 20445 } 20446 else 20447 { 20448 // the initializer list describes an array -> create array 20449 m_data.m_type = value_t::array; 20450 m_data.m_value.array = create<array_t>(init.begin(), init.end()); 20451 } 20452 20453 set_parents(); 20454 assert_invariant(); 20455 } 20456 20457 /// @brief explicitly create a binary array (without subtype) 20458 /// @sa https://json.nlohmann.me/api/basic_json/binary/ 20459 JSON_HEDLEY_WARN_UNUSED_RESULT 20460 static basic_json binary(const typename binary_t::container_type& init) 20461 { 20462 auto res = basic_json(); 20463 res.m_data.m_type = value_t::binary; 20464 res.m_data.m_value = init; 20465 return res; 20466 } 20467 20468 /// @brief explicitly create a binary array (with subtype) 20469 /// @sa https://json.nlohmann.me/api/basic_json/binary/ 20470 JSON_HEDLEY_WARN_UNUSED_RESULT 20471 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype) 20472 { 20473 auto res = basic_json(); 20474 res.m_data.m_type = value_t::binary; 20475 res.m_data.m_value = binary_t(init, subtype); 20476 return res; 20477 } 20478 20479 /// @brief explicitly create a binary array 20480 /// @sa https://json.nlohmann.me/api/basic_json/binary/ 20481 JSON_HEDLEY_WARN_UNUSED_RESULT 20482 static basic_json binary(typename binary_t::container_type&& init) 20483 { 20484 auto res = basic_json(); 20485 res.m_data.m_type = value_t::binary; 20486 res.m_data.m_value = std::move(init); 20487 return res; 20488 } 20489 20490 /// @brief explicitly create a binary array (with subtype) 20491 /// @sa https://json.nlohmann.me/api/basic_json/binary/ 20492 JSON_HEDLEY_WARN_UNUSED_RESULT 20493 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype) 20494 { 20495 auto res = basic_json(); 20496 res.m_data.m_type = value_t::binary; 20497 res.m_data.m_value = binary_t(std::move(init), subtype); 20498 return res; 20499 } 20500 20501 /// @brief explicitly create an array from an initializer list 20502 /// @sa https://json.nlohmann.me/api/basic_json/array/ 20503 JSON_HEDLEY_WARN_UNUSED_RESULT 20504 static basic_json array(initializer_list_t init = {}) 20505 { 20506 return basic_json(init, false, value_t::array); 20507 } 20508 20509 /// @brief explicitly create an object from an initializer list 20510 /// @sa https://json.nlohmann.me/api/basic_json/object/ 20511 JSON_HEDLEY_WARN_UNUSED_RESULT 20512 static basic_json object(initializer_list_t init = {}) 20513 { 20514 return basic_json(init, false, value_t::object); 20515 } 20516 20517 /// @brief construct an array with count copies of given value 20518 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20519 basic_json(size_type cnt, const basic_json& val): 20520 m_data{cnt, val} 20521 { 20522 set_parents(); 20523 assert_invariant(); 20524 } 20525 20526 /// @brief construct a JSON container given an iterator range 20527 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20528 template < class InputIT, typename std::enable_if < 20529 std::is_same<InputIT, typename basic_json_t::iterator>::value || 20530 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 > 20531 basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param) 20532 { 20533 JSON_ASSERT(first.m_object != nullptr); 20534 JSON_ASSERT(last.m_object != nullptr); 20535 20536 // make sure iterator fits the current value 20537 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) 20538 { 20539 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr)); 20540 } 20541 20542 // copy type from first iterator 20543 m_data.m_type = first.m_object->m_data.m_type; 20544 20545 // check if iterator range is complete for primitive values 20546 switch (m_data.m_type) 20547 { 20548 case value_t::boolean: 20549 case value_t::number_float: 20550 case value_t::number_integer: 20551 case value_t::number_unsigned: 20552 case value_t::string: 20553 { 20554 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin() 20555 || !last.m_it.primitive_iterator.is_end())) 20556 { 20557 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object)); 20558 } 20559 break; 20560 } 20561 20562 case value_t::null: 20563 case value_t::object: 20564 case value_t::array: 20565 case value_t::binary: 20566 case value_t::discarded: 20567 default: 20568 break; 20569 } 20570 20571 switch (m_data.m_type) 20572 { 20573 case value_t::number_integer: 20574 { 20575 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer; 20576 break; 20577 } 20578 20579 case value_t::number_unsigned: 20580 { 20581 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned; 20582 break; 20583 } 20584 20585 case value_t::number_float: 20586 { 20587 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float; 20588 break; 20589 } 20590 20591 case value_t::boolean: 20592 { 20593 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean; 20594 break; 20595 } 20596 20597 case value_t::string: 20598 { 20599 m_data.m_value = *first.m_object->m_data.m_value.string; 20600 break; 20601 } 20602 20603 case value_t::object: 20604 { 20605 m_data.m_value.object = create<object_t>(first.m_it.object_iterator, 20606 last.m_it.object_iterator); 20607 break; 20608 } 20609 20610 case value_t::array: 20611 { 20612 m_data.m_value.array = create<array_t>(first.m_it.array_iterator, 20613 last.m_it.array_iterator); 20614 break; 20615 } 20616 20617 case value_t::binary: 20618 { 20619 m_data.m_value = *first.m_object->m_data.m_value.binary; 20620 break; 20621 } 20622 20623 case value_t::null: 20624 case value_t::discarded: 20625 default: 20626 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object)); 20627 } 20628 20629 set_parents(); 20630 assert_invariant(); 20631 } 20632 20633 /////////////////////////////////////// 20634 // other constructors and destructor // 20635 /////////////////////////////////////// 20636 20637 template<typename JsonRef, 20638 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>, 20639 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 > 20640 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {} 20641 20642 /// @brief copy constructor 20643 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20644 basic_json(const basic_json& other) 20645 : json_base_class_t(other) 20646 { 20647 m_data.m_type = other.m_data.m_type; 20648 // check of passed value is valid 20649 other.assert_invariant(); 20650 20651 switch (m_data.m_type) 20652 { 20653 case value_t::object: 20654 { 20655 m_data.m_value = *other.m_data.m_value.object; 20656 break; 20657 } 20658 20659 case value_t::array: 20660 { 20661 m_data.m_value = *other.m_data.m_value.array; 20662 break; 20663 } 20664 20665 case value_t::string: 20666 { 20667 m_data.m_value = *other.m_data.m_value.string; 20668 break; 20669 } 20670 20671 case value_t::boolean: 20672 { 20673 m_data.m_value = other.m_data.m_value.boolean; 20674 break; 20675 } 20676 20677 case value_t::number_integer: 20678 { 20679 m_data.m_value = other.m_data.m_value.number_integer; 20680 break; 20681 } 20682 20683 case value_t::number_unsigned: 20684 { 20685 m_data.m_value = other.m_data.m_value.number_unsigned; 20686 break; 20687 } 20688 20689 case value_t::number_float: 20690 { 20691 m_data.m_value = other.m_data.m_value.number_float; 20692 break; 20693 } 20694 20695 case value_t::binary: 20696 { 20697 m_data.m_value = *other.m_data.m_value.binary; 20698 break; 20699 } 20700 20701 case value_t::null: 20702 case value_t::discarded: 20703 default: 20704 break; 20705 } 20706 20707 set_parents(); 20708 assert_invariant(); 20709 } 20710 20711 /// @brief move constructor 20712 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20713 basic_json(basic_json&& other) noexcept 20714 : json_base_class_t(std::forward<json_base_class_t>(other)), 20715 m_data(std::move(other.m_data)) 20716 { 20717 // check that passed value is valid 20718 other.assert_invariant(false); 20719 20720 // invalidate payload 20721 other.m_data.m_type = value_t::null; 20722 other.m_data.m_value = {}; 20723 20724 set_parents(); 20725 assert_invariant(); 20726 } 20727 20728 /// @brief copy assignment 20729 /// @sa https://json.nlohmann.me/api/basic_json/operator=/ 20730 basic_json& operator=(basic_json other) noexcept ( 20731 std::is_nothrow_move_constructible<value_t>::value&& 20732 std::is_nothrow_move_assignable<value_t>::value&& 20733 std::is_nothrow_move_constructible<json_value>::value&& 20734 std::is_nothrow_move_assignable<json_value>::value&& 20735 std::is_nothrow_move_assignable<json_base_class_t>::value 20736 ) 20737 { 20738 // check that passed value is valid 20739 other.assert_invariant(); 20740 20741 using std::swap; 20742 swap(m_data.m_type, other.m_data.m_type); 20743 swap(m_data.m_value, other.m_data.m_value); 20744 json_base_class_t::operator=(std::move(other)); 20745 20746 set_parents(); 20747 assert_invariant(); 20748 return *this; 20749 } 20750 20751 /// @brief destructor 20752 /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/ 20753 ~basic_json() noexcept 20754 { 20755 assert_invariant(false); 20756 } 20757 20758 /// @} 20759 20760 public: 20761 /////////////////////// 20762 // object inspection // 20763 /////////////////////// 20764 20765 /// @name object inspection 20766 /// Functions to inspect the type of a JSON value. 20767 /// @{ 20768 20769 /// @brief serialization 20770 /// @sa https://json.nlohmann.me/api/basic_json/dump/ 20771 string_t dump(const int indent = -1, 20772 const char indent_char = ' ', 20773 const bool ensure_ascii = false, 20774 const error_handler_t error_handler = error_handler_t::strict) const 20775 { 20776 string_t result; 20777 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler); 20778 20779 if (indent >= 0) 20780 { 20781 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent)); 20782 } 20783 else 20784 { 20785 s.dump(*this, false, ensure_ascii, 0); 20786 } 20787 20788 return result; 20789 } 20790 20791 /// @brief return the type of the JSON value (explicit) 20792 /// @sa https://json.nlohmann.me/api/basic_json/type/ 20793 constexpr value_t type() const noexcept 20794 { 20795 return m_data.m_type; 20796 } 20797 20798 /// @brief return whether type is primitive 20799 /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/ 20800 constexpr bool is_primitive() const noexcept 20801 { 20802 return is_null() || is_string() || is_boolean() || is_number() || is_binary(); 20803 } 20804 20805 /// @brief return whether type is structured 20806 /// @sa https://json.nlohmann.me/api/basic_json/is_structured/ 20807 constexpr bool is_structured() const noexcept 20808 { 20809 return is_array() || is_object(); 20810 } 20811 20812 /// @brief return whether value is null 20813 /// @sa https://json.nlohmann.me/api/basic_json/is_null/ 20814 constexpr bool is_null() const noexcept 20815 { 20816 return m_data.m_type == value_t::null; 20817 } 20818 20819 /// @brief return whether value is a boolean 20820 /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/ 20821 constexpr bool is_boolean() const noexcept 20822 { 20823 return m_data.m_type == value_t::boolean; 20824 } 20825 20826 /// @brief return whether value is a number 20827 /// @sa https://json.nlohmann.me/api/basic_json/is_number/ 20828 constexpr bool is_number() const noexcept 20829 { 20830 return is_number_integer() || is_number_float(); 20831 } 20832 20833 /// @brief return whether value is an integer number 20834 /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/ 20835 constexpr bool is_number_integer() const noexcept 20836 { 20837 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned; 20838 } 20839 20840 /// @brief return whether value is an unsigned integer number 20841 /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/ 20842 constexpr bool is_number_unsigned() const noexcept 20843 { 20844 return m_data.m_type == value_t::number_unsigned; 20845 } 20846 20847 /// @brief return whether value is a floating-point number 20848 /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/ 20849 constexpr bool is_number_float() const noexcept 20850 { 20851 return m_data.m_type == value_t::number_float; 20852 } 20853 20854 /// @brief return whether value is an object 20855 /// @sa https://json.nlohmann.me/api/basic_json/is_object/ 20856 constexpr bool is_object() const noexcept 20857 { 20858 return m_data.m_type == value_t::object; 20859 } 20860 20861 /// @brief return whether value is an array 20862 /// @sa https://json.nlohmann.me/api/basic_json/is_array/ 20863 constexpr bool is_array() const noexcept 20864 { 20865 return m_data.m_type == value_t::array; 20866 } 20867 20868 /// @brief return whether value is a string 20869 /// @sa https://json.nlohmann.me/api/basic_json/is_string/ 20870 constexpr bool is_string() const noexcept 20871 { 20872 return m_data.m_type == value_t::string; 20873 } 20874 20875 /// @brief return whether value is a binary array 20876 /// @sa https://json.nlohmann.me/api/basic_json/is_binary/ 20877 constexpr bool is_binary() const noexcept 20878 { 20879 return m_data.m_type == value_t::binary; 20880 } 20881 20882 /// @brief return whether value is discarded 20883 /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/ 20884 constexpr bool is_discarded() const noexcept 20885 { 20886 return m_data.m_type == value_t::discarded; 20887 } 20888 20889 /// @brief return the type of the JSON value (implicit) 20890 /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/ 20891 constexpr operator value_t() const noexcept 20892 { 20893 return m_data.m_type; 20894 } 20895 20896 /// @} 20897 20898 private: 20899 ////////////////// 20900 // value access // 20901 ////////////////// 20902 20903 /// get a boolean (explicit) 20904 boolean_t get_impl(boolean_t* /*unused*/) const 20905 { 20906 if (JSON_HEDLEY_LIKELY(is_boolean())) 20907 { 20908 return m_data.m_value.boolean; 20909 } 20910 20911 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this)); 20912 } 20913 20914 /// get a pointer to the value (object) 20915 object_t* get_impl_ptr(object_t* /*unused*/) noexcept 20916 { 20917 return is_object() ? m_data.m_value.object : nullptr; 20918 } 20919 20920 /// get a pointer to the value (object) 20921 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept 20922 { 20923 return is_object() ? m_data.m_value.object : nullptr; 20924 } 20925 20926 /// get a pointer to the value (array) 20927 array_t* get_impl_ptr(array_t* /*unused*/) noexcept 20928 { 20929 return is_array() ? m_data.m_value.array : nullptr; 20930 } 20931 20932 /// get a pointer to the value (array) 20933 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept 20934 { 20935 return is_array() ? m_data.m_value.array : nullptr; 20936 } 20937 20938 /// get a pointer to the value (string) 20939 string_t* get_impl_ptr(string_t* /*unused*/) noexcept 20940 { 20941 return is_string() ? m_data.m_value.string : nullptr; 20942 } 20943 20944 /// get a pointer to the value (string) 20945 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept 20946 { 20947 return is_string() ? m_data.m_value.string : nullptr; 20948 } 20949 20950 /// get a pointer to the value (boolean) 20951 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept 20952 { 20953 return is_boolean() ? &m_data.m_value.boolean : nullptr; 20954 } 20955 20956 /// get a pointer to the value (boolean) 20957 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept 20958 { 20959 return is_boolean() ? &m_data.m_value.boolean : nullptr; 20960 } 20961 20962 /// get a pointer to the value (integer number) 20963 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept 20964 { 20965 return is_number_integer() ? &m_data.m_value.number_integer : nullptr; 20966 } 20967 20968 /// get a pointer to the value (integer number) 20969 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept 20970 { 20971 return is_number_integer() ? &m_data.m_value.number_integer : nullptr; 20972 } 20973 20974 /// get a pointer to the value (unsigned number) 20975 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept 20976 { 20977 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr; 20978 } 20979 20980 /// get a pointer to the value (unsigned number) 20981 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept 20982 { 20983 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr; 20984 } 20985 20986 /// get a pointer to the value (floating-point number) 20987 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept 20988 { 20989 return is_number_float() ? &m_data.m_value.number_float : nullptr; 20990 } 20991 20992 /// get a pointer to the value (floating-point number) 20993 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept 20994 { 20995 return is_number_float() ? &m_data.m_value.number_float : nullptr; 20996 } 20997 20998 /// get a pointer to the value (binary) 20999 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept 21000 { 21001 return is_binary() ? m_data.m_value.binary : nullptr; 21002 } 21003 21004 /// get a pointer to the value (binary) 21005 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept 21006 { 21007 return is_binary() ? m_data.m_value.binary : nullptr; 21008 } 21009 21010 /*! 21011 @brief helper function to implement get_ref() 21012 21013 This function helps to implement get_ref() without code duplication for 21014 const and non-const overloads 21015 21016 @tparam ThisType will be deduced as `basic_json` or `const basic_json` 21017 21018 @throw type_error.303 if ReferenceType does not match underlying value 21019 type of the current JSON 21020 */ 21021 template<typename ReferenceType, typename ThisType> 21022 static ReferenceType get_ref_impl(ThisType& obj) 21023 { 21024 // delegate the call to get_ptr<>() 21025 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>(); 21026 21027 if (JSON_HEDLEY_LIKELY(ptr != nullptr)) 21028 { 21029 return *ptr; 21030 } 21031 21032 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj)); 21033 } 21034 21035 public: 21036 /// @name value access 21037 /// Direct access to the stored value of a JSON value. 21038 /// @{ 21039 21040 /// @brief get a pointer value (implicit) 21041 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/ 21042 template<typename PointerType, typename std::enable_if< 21043 std::is_pointer<PointerType>::value, int>::type = 0> 21044 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) 21045 { 21046 // delegate the call to get_impl_ptr<>() 21047 return get_impl_ptr(static_cast<PointerType>(nullptr)); 21048 } 21049 21050 /// @brief get a pointer value (implicit) 21051 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/ 21052 template < typename PointerType, typename std::enable_if < 21053 std::is_pointer<PointerType>::value&& 21054 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 > 21055 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) 21056 { 21057 // delegate the call to get_impl_ptr<>() const 21058 return get_impl_ptr(static_cast<PointerType>(nullptr)); 21059 } 21060 21061 private: 21062 /*! 21063 @brief get a value (explicit) 21064 21065 Explicit type conversion between the JSON value and a compatible value 21066 which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) 21067 and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). 21068 The value is converted by calling the @ref json_serializer<ValueType> 21069 `from_json()` method. 21070 21071 The function is equivalent to executing 21072 @code {.cpp} 21073 ValueType ret; 21074 JSONSerializer<ValueType>::from_json(*this, ret); 21075 return ret; 21076 @endcode 21077 21078 This overloads is chosen if: 21079 - @a ValueType is not @ref basic_json, 21080 - @ref json_serializer<ValueType> has a `from_json()` method of the form 21081 `void from_json(const basic_json&, ValueType&)`, and 21082 - @ref json_serializer<ValueType> does not have a `from_json()` method of 21083 the form `ValueType from_json(const basic_json&)` 21084 21085 @tparam ValueType the returned value type 21086 21087 @return copy of the JSON value, converted to @a ValueType 21088 21089 @throw what @ref json_serializer<ValueType> `from_json()` method throws 21090 21091 @liveexample{The example below shows several conversions from JSON values 21092 to other types. There a few things to note: (1) Floating-point numbers can 21093 be converted to integers\, (2) A JSON array can be converted to a standard 21094 `std::vector<short>`\, (3) A JSON object can be converted to C++ 21095 associative containers such as `std::unordered_map<std::string\, 21096 json>`.,get__ValueType_const} 21097 21098 @since version 2.1.0 21099 */ 21100 template < typename ValueType, 21101 detail::enable_if_t < 21102 detail::is_default_constructible<ValueType>::value&& 21103 detail::has_from_json<basic_json_t, ValueType>::value, 21104 int > = 0 > 21105 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept( 21106 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>()))) 21107 { 21108 auto ret = ValueType(); 21109 JSONSerializer<ValueType>::from_json(*this, ret); 21110 return ret; 21111 } 21112 21113 /*! 21114 @brief get a value (explicit); special case 21115 21116 Explicit type conversion between the JSON value and a compatible value 21117 which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) 21118 and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). 21119 The value is converted by calling the @ref json_serializer<ValueType> 21120 `from_json()` method. 21121 21122 The function is equivalent to executing 21123 @code {.cpp} 21124 return JSONSerializer<ValueType>::from_json(*this); 21125 @endcode 21126 21127 This overloads is chosen if: 21128 - @a ValueType is not @ref basic_json and 21129 - @ref json_serializer<ValueType> has a `from_json()` method of the form 21130 `ValueType from_json(const basic_json&)` 21131 21132 @note If @ref json_serializer<ValueType> has both overloads of 21133 `from_json()`, this one is chosen. 21134 21135 @tparam ValueType the returned value type 21136 21137 @return copy of the JSON value, converted to @a ValueType 21138 21139 @throw what @ref json_serializer<ValueType> `from_json()` method throws 21140 21141 @since version 2.1.0 21142 */ 21143 template < typename ValueType, 21144 detail::enable_if_t < 21145 detail::has_non_default_from_json<basic_json_t, ValueType>::value, 21146 int > = 0 > 21147 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept( 21148 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>()))) 21149 { 21150 return JSONSerializer<ValueType>::from_json(*this); 21151 } 21152 21153 /*! 21154 @brief get special-case overload 21155 21156 This overloads converts the current @ref basic_json in a different 21157 @ref basic_json type 21158 21159 @tparam BasicJsonType == @ref basic_json 21160 21161 @return a copy of *this, converted into @a BasicJsonType 21162 21163 @complexity Depending on the implementation of the called `from_json()` 21164 method. 21165 21166 @since version 3.2.0 21167 */ 21168 template < typename BasicJsonType, 21169 detail::enable_if_t < 21170 detail::is_basic_json<BasicJsonType>::value, 21171 int > = 0 > 21172 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const 21173 { 21174 return *this; 21175 } 21176 21177 /*! 21178 @brief get special-case overload 21179 21180 This overloads avoids a lot of template boilerplate, it can be seen as the 21181 identity method 21182 21183 @tparam BasicJsonType == @ref basic_json 21184 21185 @return a copy of *this 21186 21187 @complexity Constant. 21188 21189 @since version 2.1.0 21190 */ 21191 template<typename BasicJsonType, 21192 detail::enable_if_t< 21193 std::is_same<BasicJsonType, basic_json_t>::value, 21194 int> = 0> 21195 basic_json get_impl(detail::priority_tag<3> /*unused*/) const 21196 { 21197 return *this; 21198 } 21199 21200 /*! 21201 @brief get a pointer value (explicit) 21202 @copydoc get() 21203 */ 21204 template<typename PointerType, 21205 detail::enable_if_t< 21206 std::is_pointer<PointerType>::value, 21207 int> = 0> 21208 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept 21209 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>()) 21210 { 21211 // delegate the call to get_ptr 21212 return get_ptr<PointerType>(); 21213 } 21214 21215 public: 21216 /*! 21217 @brief get a (pointer) value (explicit) 21218 21219 Performs explicit type conversion between the JSON value and a compatible value if required. 21220 21221 - If the requested type is a pointer to the internally stored JSON value that pointer is returned. 21222 No copies are made. 21223 21224 - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible 21225 from the current @ref basic_json. 21226 21227 - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()` 21228 method. 21229 21230 @tparam ValueTypeCV the provided value type 21231 @tparam ValueType the returned value type 21232 21233 @return copy of the JSON value, converted to @tparam ValueType if necessary 21234 21235 @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required 21236 21237 @since version 2.1.0 21238 */ 21239 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>> 21240 #if defined(JSON_HAS_CPP_14) 21241 constexpr 21242 #endif 21243 auto get() const noexcept( 21244 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))) 21245 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})) 21246 { 21247 // we cannot static_assert on ValueTypeCV being non-const, because 21248 // there is support for get<const basic_json_t>(), which is why we 21249 // still need the uncvref 21250 static_assert(!std::is_reference<ValueTypeCV>::value, 21251 "get() cannot be used with reference types, you might want to use get_ref()"); 21252 return get_impl<ValueType>(detail::priority_tag<4> {}); 21253 } 21254 21255 /*! 21256 @brief get a pointer value (explicit) 21257 21258 Explicit pointer access to the internally stored JSON value. No copies are 21259 made. 21260 21261 @warning The pointer becomes invalid if the underlying JSON object 21262 changes. 21263 21264 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref 21265 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, 21266 @ref number_unsigned_t, or @ref number_float_t. 21267 21268 @return pointer to the internally stored JSON value if the requested 21269 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise 21270 21271 @complexity Constant. 21272 21273 @liveexample{The example below shows how pointers to internal values of a 21274 JSON value can be requested. Note that no type conversions are made and a 21275 `nullptr` is returned if the value and the requested pointer type does not 21276 match.,get__PointerType} 21277 21278 @sa see @ref get_ptr() for explicit pointer-member access 21279 21280 @since version 1.0.0 21281 */ 21282 template<typename PointerType, typename std::enable_if< 21283 std::is_pointer<PointerType>::value, int>::type = 0> 21284 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>()) 21285 { 21286 // delegate the call to get_ptr 21287 return get_ptr<PointerType>(); 21288 } 21289 21290 /// @brief get a value (explicit) 21291 /// @sa https://json.nlohmann.me/api/basic_json/get_to/ 21292 template < typename ValueType, 21293 detail::enable_if_t < 21294 !detail::is_basic_json<ValueType>::value&& 21295 detail::has_from_json<basic_json_t, ValueType>::value, 21296 int > = 0 > 21297 ValueType & get_to(ValueType& v) const noexcept(noexcept( 21298 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v))) 21299 { 21300 JSONSerializer<ValueType>::from_json(*this, v); 21301 return v; 21302 } 21303 21304 // specialization to allow calling get_to with a basic_json value 21305 // see https://github.com/nlohmann/json/issues/2175 21306 template<typename ValueType, 21307 detail::enable_if_t < 21308 detail::is_basic_json<ValueType>::value, 21309 int> = 0> 21310 ValueType & get_to(ValueType& v) const 21311 { 21312 v = *this; 21313 return v; 21314 } 21315 21316 template < 21317 typename T, std::size_t N, 21318 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 21319 detail::enable_if_t < 21320 detail::has_from_json<basic_json_t, Array>::value, int > = 0 > 21321 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 21322 noexcept(noexcept(JSONSerializer<Array>::from_json( 21323 std::declval<const basic_json_t&>(), v))) 21324 { 21325 JSONSerializer<Array>::from_json(*this, v); 21326 return v; 21327 } 21328 21329 /// @brief get a reference value (implicit) 21330 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/ 21331 template<typename ReferenceType, typename std::enable_if< 21332 std::is_reference<ReferenceType>::value, int>::type = 0> 21333 ReferenceType get_ref() 21334 { 21335 // delegate call to get_ref_impl 21336 return get_ref_impl<ReferenceType>(*this); 21337 } 21338 21339 /// @brief get a reference value (implicit) 21340 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/ 21341 template < typename ReferenceType, typename std::enable_if < 21342 std::is_reference<ReferenceType>::value&& 21343 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 > 21344 ReferenceType get_ref() const 21345 { 21346 // delegate call to get_ref_impl 21347 return get_ref_impl<ReferenceType>(*this); 21348 } 21349 21350 /*! 21351 @brief get a value (implicit) 21352 21353 Implicit type conversion between the JSON value and a compatible value. 21354 The call is realized by calling @ref get() const. 21355 21356 @tparam ValueType non-pointer type compatible to the JSON value, for 21357 instance `int` for JSON integer numbers, `bool` for JSON booleans, or 21358 `std::vector` types for JSON arrays. The character type of @ref string_t 21359 as well as an initializer list of this type is excluded to avoid 21360 ambiguities as these types implicitly convert to `std::string`. 21361 21362 @return copy of the JSON value, converted to type @a ValueType 21363 21364 @throw type_error.302 in case passed type @a ValueType is incompatible 21365 to the JSON value type (e.g., the JSON value is of type boolean, but a 21366 string is requested); see example below 21367 21368 @complexity Linear in the size of the JSON value. 21369 21370 @liveexample{The example below shows several conversions from JSON values 21371 to other types. There a few things to note: (1) Floating-point numbers can 21372 be converted to integers\, (2) A JSON array can be converted to a standard 21373 `std::vector<short>`\, (3) A JSON object can be converted to C++ 21374 associative containers such as `std::unordered_map<std::string\, 21375 json>`.,operator__ValueType} 21376 21377 @since version 1.0.0 21378 */ 21379 template < typename ValueType, typename std::enable_if < 21380 detail::conjunction < 21381 detail::negation<std::is_pointer<ValueType>>, 21382 detail::negation<std::is_same<ValueType, std::nullptr_t>>, 21383 detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>, 21384 detail::negation<std::is_same<ValueType, typename string_t::value_type>>, 21385 detail::negation<detail::is_basic_json<ValueType>>, 21386 detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>, 21387 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914)) 21388 detail::negation<std::is_same<ValueType, std::string_view>>, 21389 #endif 21390 #if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI 21391 detail::negation<std::is_same<ValueType, std::any>>, 21392 #endif 21393 detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType> 21394 >::value, int >::type = 0 > 21395 JSON_EXPLICIT operator ValueType() const 21396 { 21397 // delegate the call to get<>() const 21398 return get<ValueType>(); 21399 } 21400 21401 /// @brief get a binary value 21402 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/ 21403 binary_t& get_binary() 21404 { 21405 if (!is_binary()) 21406 { 21407 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this)); 21408 } 21409 21410 return *get_ptr<binary_t*>(); 21411 } 21412 21413 /// @brief get a binary value 21414 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/ 21415 const binary_t& get_binary() const 21416 { 21417 if (!is_binary()) 21418 { 21419 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this)); 21420 } 21421 21422 return *get_ptr<const binary_t*>(); 21423 } 21424 21425 /// @} 21426 21427 //////////////////// 21428 // element access // 21429 //////////////////// 21430 21431 /// @name element access 21432 /// Access to the JSON value. 21433 /// @{ 21434 21435 /// @brief access specified array element with bounds checking 21436 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21437 reference at(size_type idx) 21438 { 21439 // at only works for arrays 21440 if (JSON_HEDLEY_LIKELY(is_array())) 21441 { 21442 JSON_TRY 21443 { 21444 return set_parent(m_data.m_value.array->at(idx)); 21445 } 21446 JSON_CATCH (std::out_of_range&) 21447 { 21448 // create better exception explanation 21449 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); 21450 } 21451 } 21452 else 21453 { 21454 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21455 } 21456 } 21457 21458 /// @brief access specified array element with bounds checking 21459 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21460 const_reference at(size_type idx) const 21461 { 21462 // at only works for arrays 21463 if (JSON_HEDLEY_LIKELY(is_array())) 21464 { 21465 JSON_TRY 21466 { 21467 return m_data.m_value.array->at(idx); 21468 } 21469 JSON_CATCH (std::out_of_range&) 21470 { 21471 // create better exception explanation 21472 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); 21473 } 21474 } 21475 else 21476 { 21477 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21478 } 21479 } 21480 21481 /// @brief access specified object element with bounds checking 21482 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21483 reference at(const typename object_t::key_type& key) 21484 { 21485 // at only works for objects 21486 if (JSON_HEDLEY_UNLIKELY(!is_object())) 21487 { 21488 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21489 } 21490 21491 auto it = m_data.m_value.object->find(key); 21492 if (it == m_data.m_value.object->end()) 21493 { 21494 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); 21495 } 21496 return set_parent(it->second); 21497 } 21498 21499 /// @brief access specified object element with bounds checking 21500 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21501 template<class KeyType, detail::enable_if_t< 21502 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 21503 reference at(KeyType && key) 21504 { 21505 // at only works for objects 21506 if (JSON_HEDLEY_UNLIKELY(!is_object())) 21507 { 21508 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21509 } 21510 21511 auto it = m_data.m_value.object->find(std::forward<KeyType>(key)); 21512 if (it == m_data.m_value.object->end()) 21513 { 21514 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this)); 21515 } 21516 return set_parent(it->second); 21517 } 21518 21519 /// @brief access specified object element with bounds checking 21520 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21521 const_reference at(const typename object_t::key_type& key) const 21522 { 21523 // at only works for objects 21524 if (JSON_HEDLEY_UNLIKELY(!is_object())) 21525 { 21526 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21527 } 21528 21529 auto it = m_data.m_value.object->find(key); 21530 if (it == m_data.m_value.object->end()) 21531 { 21532 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); 21533 } 21534 return it->second; 21535 } 21536 21537 /// @brief access specified object element with bounds checking 21538 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21539 template<class KeyType, detail::enable_if_t< 21540 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 21541 const_reference at(KeyType && key) const 21542 { 21543 // at only works for objects 21544 if (JSON_HEDLEY_UNLIKELY(!is_object())) 21545 { 21546 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21547 } 21548 21549 auto it = m_data.m_value.object->find(std::forward<KeyType>(key)); 21550 if (it == m_data.m_value.object->end()) 21551 { 21552 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this)); 21553 } 21554 return it->second; 21555 } 21556 21557 /// @brief access specified array element 21558 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21559 reference operator[](size_type idx) 21560 { 21561 // implicitly convert null value to an empty array 21562 if (is_null()) 21563 { 21564 m_data.m_type = value_t::array; 21565 m_data.m_value.array = create<array_t>(); 21566 assert_invariant(); 21567 } 21568 21569 // operator[] only works for arrays 21570 if (JSON_HEDLEY_LIKELY(is_array())) 21571 { 21572 // fill up array with null values if given idx is outside range 21573 if (idx >= m_data.m_value.array->size()) 21574 { 21575 #if JSON_DIAGNOSTICS 21576 // remember array size & capacity before resizing 21577 const auto old_size = m_data.m_value.array->size(); 21578 const auto old_capacity = m_data.m_value.array->capacity(); 21579 #endif 21580 m_data.m_value.array->resize(idx + 1); 21581 21582 #if JSON_DIAGNOSTICS 21583 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) 21584 { 21585 // capacity has changed: update all parents 21586 set_parents(); 21587 } 21588 else 21589 { 21590 // set parent for values added above 21591 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size)); 21592 } 21593 #endif 21594 assert_invariant(); 21595 } 21596 21597 return m_data.m_value.array->operator[](idx); 21598 } 21599 21600 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); 21601 } 21602 21603 /// @brief access specified array element 21604 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21605 const_reference operator[](size_type idx) const 21606 { 21607 // const operator[] only works for arrays 21608 if (JSON_HEDLEY_LIKELY(is_array())) 21609 { 21610 return m_data.m_value.array->operator[](idx); 21611 } 21612 21613 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); 21614 } 21615 21616 /// @brief access specified object element 21617 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21618 reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param) 21619 { 21620 // implicitly convert null value to an empty object 21621 if (is_null()) 21622 { 21623 m_data.m_type = value_t::object; 21624 m_data.m_value.object = create<object_t>(); 21625 assert_invariant(); 21626 } 21627 21628 // operator[] only works for objects 21629 if (JSON_HEDLEY_LIKELY(is_object())) 21630 { 21631 auto result = m_data.m_value.object->emplace(std::move(key), nullptr); 21632 return set_parent(result.first->second); 21633 } 21634 21635 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); 21636 } 21637 21638 /// @brief access specified object element 21639 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21640 const_reference operator[](const typename object_t::key_type& key) const 21641 { 21642 // const operator[] only works for objects 21643 if (JSON_HEDLEY_LIKELY(is_object())) 21644 { 21645 auto it = m_data.m_value.object->find(key); 21646 JSON_ASSERT(it != m_data.m_value.object->end()); 21647 return it->second; 21648 } 21649 21650 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); 21651 } 21652 21653 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC 21654 // (they seemingly cannot be constrained to resolve the ambiguity) 21655 template<typename T> 21656 reference operator[](T* key) 21657 { 21658 return operator[](typename object_t::key_type(key)); 21659 } 21660 21661 template<typename T> 21662 const_reference operator[](T* key) const 21663 { 21664 return operator[](typename object_t::key_type(key)); 21665 } 21666 21667 /// @brief access specified object element 21668 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21669 template<class KeyType, detail::enable_if_t< 21670 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 > 21671 reference operator[](KeyType && key) 21672 { 21673 // implicitly convert null value to an empty object 21674 if (is_null()) 21675 { 21676 m_data.m_type = value_t::object; 21677 m_data.m_value.object = create<object_t>(); 21678 assert_invariant(); 21679 } 21680 21681 // operator[] only works for objects 21682 if (JSON_HEDLEY_LIKELY(is_object())) 21683 { 21684 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr); 21685 return set_parent(result.first->second); 21686 } 21687 21688 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); 21689 } 21690 21691 /// @brief access specified object element 21692 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21693 template<class KeyType, detail::enable_if_t< 21694 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 > 21695 const_reference operator[](KeyType && key) const 21696 { 21697 // const operator[] only works for objects 21698 if (JSON_HEDLEY_LIKELY(is_object())) 21699 { 21700 auto it = m_data.m_value.object->find(std::forward<KeyType>(key)); 21701 JSON_ASSERT(it != m_data.m_value.object->end()); 21702 return it->second; 21703 } 21704 21705 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); 21706 } 21707 21708 private: 21709 template<typename KeyType> 21710 using is_comparable_with_object_key = detail::is_comparable < 21711 object_comparator_t, const typename object_t::key_type&, KeyType >; 21712 21713 template<typename ValueType> 21714 using value_return_type = std::conditional < 21715 detail::is_c_string_uncvref<ValueType>::value, 21716 string_t, typename std::decay<ValueType>::type >; 21717 21718 public: 21719 /// @brief access specified object element with default value 21720 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21721 template < class ValueType, detail::enable_if_t < 21722 !detail::is_transparent<object_comparator_t>::value 21723 && detail::is_getable<basic_json_t, ValueType>::value 21724 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21725 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const 21726 { 21727 // value only works for objects 21728 if (JSON_HEDLEY_LIKELY(is_object())) 21729 { 21730 // if key is found, return value and given default value otherwise 21731 const auto it = find(key); 21732 if (it != end()) 21733 { 21734 return it->template get<ValueType>(); 21735 } 21736 21737 return default_value; 21738 } 21739 21740 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21741 } 21742 21743 /// @brief access specified object element with default value 21744 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21745 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type, 21746 detail::enable_if_t < 21747 !detail::is_transparent<object_comparator_t>::value 21748 && detail::is_getable<basic_json_t, ReturnType>::value 21749 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21750 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const 21751 { 21752 // value only works for objects 21753 if (JSON_HEDLEY_LIKELY(is_object())) 21754 { 21755 // if key is found, return value and given default value otherwise 21756 const auto it = find(key); 21757 if (it != end()) 21758 { 21759 return it->template get<ReturnType>(); 21760 } 21761 21762 return std::forward<ValueType>(default_value); 21763 } 21764 21765 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21766 } 21767 21768 /// @brief access specified object element with default value 21769 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21770 template < class ValueType, class KeyType, detail::enable_if_t < 21771 detail::is_transparent<object_comparator_t>::value 21772 && !detail::is_json_pointer<KeyType>::value 21773 && is_comparable_with_object_key<KeyType>::value 21774 && detail::is_getable<basic_json_t, ValueType>::value 21775 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21776 ValueType value(KeyType && key, const ValueType& default_value) const 21777 { 21778 // value only works for objects 21779 if (JSON_HEDLEY_LIKELY(is_object())) 21780 { 21781 // if key is found, return value and given default value otherwise 21782 const auto it = find(std::forward<KeyType>(key)); 21783 if (it != end()) 21784 { 21785 return it->template get<ValueType>(); 21786 } 21787 21788 return default_value; 21789 } 21790 21791 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21792 } 21793 21794 /// @brief access specified object element via JSON Pointer with default value 21795 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21796 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type, 21797 detail::enable_if_t < 21798 detail::is_transparent<object_comparator_t>::value 21799 && !detail::is_json_pointer<KeyType>::value 21800 && is_comparable_with_object_key<KeyType>::value 21801 && detail::is_getable<basic_json_t, ReturnType>::value 21802 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21803 ReturnType value(KeyType && key, ValueType && default_value) const 21804 { 21805 // value only works for objects 21806 if (JSON_HEDLEY_LIKELY(is_object())) 21807 { 21808 // if key is found, return value and given default value otherwise 21809 const auto it = find(std::forward<KeyType>(key)); 21810 if (it != end()) 21811 { 21812 return it->template get<ReturnType>(); 21813 } 21814 21815 return std::forward<ValueType>(default_value); 21816 } 21817 21818 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21819 } 21820 21821 /// @brief access specified object element via JSON Pointer with default value 21822 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21823 template < class ValueType, detail::enable_if_t < 21824 detail::is_getable<basic_json_t, ValueType>::value 21825 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21826 ValueType value(const json_pointer& ptr, const ValueType& default_value) const 21827 { 21828 // value only works for objects 21829 if (JSON_HEDLEY_LIKELY(is_object())) 21830 { 21831 // if pointer resolves a value, return it or use default value 21832 JSON_TRY 21833 { 21834 return ptr.get_checked(this).template get<ValueType>(); 21835 } 21836 JSON_INTERNAL_CATCH (out_of_range&) 21837 { 21838 return default_value; 21839 } 21840 } 21841 21842 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21843 } 21844 21845 /// @brief access specified object element via JSON Pointer with default value 21846 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21847 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type, 21848 detail::enable_if_t < 21849 detail::is_getable<basic_json_t, ReturnType>::value 21850 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21851 ReturnType value(const json_pointer& ptr, ValueType && default_value) const 21852 { 21853 // value only works for objects 21854 if (JSON_HEDLEY_LIKELY(is_object())) 21855 { 21856 // if pointer resolves a value, return it or use default value 21857 JSON_TRY 21858 { 21859 return ptr.get_checked(this).template get<ReturnType>(); 21860 } 21861 JSON_INTERNAL_CATCH (out_of_range&) 21862 { 21863 return std::forward<ValueType>(default_value); 21864 } 21865 } 21866 21867 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21868 } 21869 21870 template < class ValueType, class BasicJsonType, detail::enable_if_t < 21871 detail::is_basic_json<BasicJsonType>::value 21872 && detail::is_getable<basic_json_t, ValueType>::value 21873 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21874 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 21875 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const 21876 { 21877 return value(ptr.convert(), default_value); 21878 } 21879 21880 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type, 21881 detail::enable_if_t < 21882 detail::is_basic_json<BasicJsonType>::value 21883 && detail::is_getable<basic_json_t, ReturnType>::value 21884 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21885 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 21886 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const 21887 { 21888 return value(ptr.convert(), std::forward<ValueType>(default_value)); 21889 } 21890 21891 /// @brief access the first element 21892 /// @sa https://json.nlohmann.me/api/basic_json/front/ 21893 reference front() 21894 { 21895 return *begin(); 21896 } 21897 21898 /// @brief access the first element 21899 /// @sa https://json.nlohmann.me/api/basic_json/front/ 21900 const_reference front() const 21901 { 21902 return *cbegin(); 21903 } 21904 21905 /// @brief access the last element 21906 /// @sa https://json.nlohmann.me/api/basic_json/back/ 21907 reference back() 21908 { 21909 auto tmp = end(); 21910 --tmp; 21911 return *tmp; 21912 } 21913 21914 /// @brief access the last element 21915 /// @sa https://json.nlohmann.me/api/basic_json/back/ 21916 const_reference back() const 21917 { 21918 auto tmp = cend(); 21919 --tmp; 21920 return *tmp; 21921 } 21922 21923 /// @brief remove element given an iterator 21924 /// @sa https://json.nlohmann.me/api/basic_json/erase/ 21925 template < class IteratorType, detail::enable_if_t < 21926 std::is_same<IteratorType, typename basic_json_t::iterator>::value || 21927 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 > 21928 IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param) 21929 { 21930 // make sure iterator fits the current value 21931 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) 21932 { 21933 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 21934 } 21935 21936 IteratorType result = end(); 21937 21938 switch (m_data.m_type) 21939 { 21940 case value_t::boolean: 21941 case value_t::number_float: 21942 case value_t::number_integer: 21943 case value_t::number_unsigned: 21944 case value_t::string: 21945 case value_t::binary: 21946 { 21947 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) 21948 { 21949 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this)); 21950 } 21951 21952 if (is_string()) 21953 { 21954 AllocatorType<string_t> alloc; 21955 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string); 21956 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1); 21957 m_data.m_value.string = nullptr; 21958 } 21959 else if (is_binary()) 21960 { 21961 AllocatorType<binary_t> alloc; 21962 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary); 21963 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1); 21964 m_data.m_value.binary = nullptr; 21965 } 21966 21967 m_data.m_type = value_t::null; 21968 assert_invariant(); 21969 break; 21970 } 21971 21972 case value_t::object: 21973 { 21974 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator); 21975 break; 21976 } 21977 21978 case value_t::array: 21979 { 21980 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator); 21981 break; 21982 } 21983 21984 case value_t::null: 21985 case value_t::discarded: 21986 default: 21987 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 21988 } 21989 21990 return result; 21991 } 21992 21993 /// @brief remove elements given an iterator range 21994 /// @sa https://json.nlohmann.me/api/basic_json/erase/ 21995 template < class IteratorType, detail::enable_if_t < 21996 std::is_same<IteratorType, typename basic_json_t::iterator>::value || 21997 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 > 21998 IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param) 21999 { 22000 // make sure iterator fits the current value 22001 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) 22002 { 22003 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this)); 22004 } 22005 22006 IteratorType result = end(); 22007 22008 switch (m_data.m_type) 22009 { 22010 case value_t::boolean: 22011 case value_t::number_float: 22012 case value_t::number_integer: 22013 case value_t::number_unsigned: 22014 case value_t::string: 22015 case value_t::binary: 22016 { 22017 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin() 22018 || !last.m_it.primitive_iterator.is_end())) 22019 { 22020 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this)); 22021 } 22022 22023 if (is_string()) 22024 { 22025 AllocatorType<string_t> alloc; 22026 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string); 22027 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1); 22028 m_data.m_value.string = nullptr; 22029 } 22030 else if (is_binary()) 22031 { 22032 AllocatorType<binary_t> alloc; 22033 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary); 22034 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1); 22035 m_data.m_value.binary = nullptr; 22036 } 22037 22038 m_data.m_type = value_t::null; 22039 assert_invariant(); 22040 break; 22041 } 22042 22043 case value_t::object: 22044 { 22045 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator, 22046 last.m_it.object_iterator); 22047 break; 22048 } 22049 22050 case value_t::array: 22051 { 22052 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator, 22053 last.m_it.array_iterator); 22054 break; 22055 } 22056 22057 case value_t::null: 22058 case value_t::discarded: 22059 default: 22060 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 22061 } 22062 22063 return result; 22064 } 22065 22066 private: 22067 template < typename KeyType, detail::enable_if_t < 22068 detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 > 22069 size_type erase_internal(KeyType && key) 22070 { 22071 // this erase only works for objects 22072 if (JSON_HEDLEY_UNLIKELY(!is_object())) 22073 { 22074 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 22075 } 22076 22077 return m_data.m_value.object->erase(std::forward<KeyType>(key)); 22078 } 22079 22080 template < typename KeyType, detail::enable_if_t < 22081 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 > 22082 size_type erase_internal(KeyType && key) 22083 { 22084 // this erase only works for objects 22085 if (JSON_HEDLEY_UNLIKELY(!is_object())) 22086 { 22087 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 22088 } 22089 22090 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key)); 22091 if (it != m_data.m_value.object->end()) 22092 { 22093 m_data.m_value.object->erase(it); 22094 return 1; 22095 } 22096 return 0; 22097 } 22098 22099 public: 22100 22101 /// @brief remove element from a JSON object given a key 22102 /// @sa https://json.nlohmann.me/api/basic_json/erase/ 22103 size_type erase(const typename object_t::key_type& key) 22104 { 22105 // the indirection via erase_internal() is added to avoid making this 22106 // function a template and thus de-rank it during overload resolution 22107 return erase_internal(key); 22108 } 22109 22110 /// @brief remove element from a JSON object given a key 22111 /// @sa https://json.nlohmann.me/api/basic_json/erase/ 22112 template<class KeyType, detail::enable_if_t< 22113 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 22114 size_type erase(KeyType && key) 22115 { 22116 return erase_internal(std::forward<KeyType>(key)); 22117 } 22118 22119 /// @brief remove element from a JSON array given an index 22120 /// @sa https://json.nlohmann.me/api/basic_json/erase/ 22121 void erase(const size_type idx) 22122 { 22123 // this erase only works for arrays 22124 if (JSON_HEDLEY_LIKELY(is_array())) 22125 { 22126 if (JSON_HEDLEY_UNLIKELY(idx >= size())) 22127 { 22128 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); 22129 } 22130 22131 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx)); 22132 } 22133 else 22134 { 22135 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 22136 } 22137 } 22138 22139 /// @} 22140 22141 //////////// 22142 // lookup // 22143 //////////// 22144 22145 /// @name lookup 22146 /// @{ 22147 22148 /// @brief find an element in a JSON object 22149 /// @sa https://json.nlohmann.me/api/basic_json/find/ 22150 iterator find(const typename object_t::key_type& key) 22151 { 22152 auto result = end(); 22153 22154 if (is_object()) 22155 { 22156 result.m_it.object_iterator = m_data.m_value.object->find(key); 22157 } 22158 22159 return result; 22160 } 22161 22162 /// @brief find an element in a JSON object 22163 /// @sa https://json.nlohmann.me/api/basic_json/find/ 22164 const_iterator find(const typename object_t::key_type& key) const 22165 { 22166 auto result = cend(); 22167 22168 if (is_object()) 22169 { 22170 result.m_it.object_iterator = m_data.m_value.object->find(key); 22171 } 22172 22173 return result; 22174 } 22175 22176 /// @brief find an element in a JSON object 22177 /// @sa https://json.nlohmann.me/api/basic_json/find/ 22178 template<class KeyType, detail::enable_if_t< 22179 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 22180 iterator find(KeyType && key) 22181 { 22182 auto result = end(); 22183 22184 if (is_object()) 22185 { 22186 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key)); 22187 } 22188 22189 return result; 22190 } 22191 22192 /// @brief find an element in a JSON object 22193 /// @sa https://json.nlohmann.me/api/basic_json/find/ 22194 template<class KeyType, detail::enable_if_t< 22195 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 22196 const_iterator find(KeyType && key) const 22197 { 22198 auto result = cend(); 22199 22200 if (is_object()) 22201 { 22202 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key)); 22203 } 22204 22205 return result; 22206 } 22207 22208 /// @brief returns the number of occurrences of a key in a JSON object 22209 /// @sa https://json.nlohmann.me/api/basic_json/count/ 22210 size_type count(const typename object_t::key_type& key) const 22211 { 22212 // return 0 for all nonobject types 22213 return is_object() ? m_data.m_value.object->count(key) : 0; 22214 } 22215 22216 /// @brief returns the number of occurrences of a key in a JSON object 22217 /// @sa https://json.nlohmann.me/api/basic_json/count/ 22218 template<class KeyType, detail::enable_if_t< 22219 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 22220 size_type count(KeyType && key) const 22221 { 22222 // return 0 for all nonobject types 22223 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0; 22224 } 22225 22226 /// @brief check the existence of an element in a JSON object 22227 /// @sa https://json.nlohmann.me/api/basic_json/contains/ 22228 bool contains(const typename object_t::key_type& key) const 22229 { 22230 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end(); 22231 } 22232 22233 /// @brief check the existence of an element in a JSON object 22234 /// @sa https://json.nlohmann.me/api/basic_json/contains/ 22235 template<class KeyType, detail::enable_if_t< 22236 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 22237 bool contains(KeyType && key) const 22238 { 22239 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end(); 22240 } 22241 22242 /// @brief check the existence of an element in a JSON object given a JSON pointer 22243 /// @sa https://json.nlohmann.me/api/basic_json/contains/ 22244 bool contains(const json_pointer& ptr) const 22245 { 22246 return ptr.contains(this); 22247 } 22248 22249 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 22250 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 22251 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const 22252 { 22253 return ptr.contains(this); 22254 } 22255 22256 /// @} 22257 22258 /////////////// 22259 // iterators // 22260 /////////////// 22261 22262 /// @name iterators 22263 /// @{ 22264 22265 /// @brief returns an iterator to the first element 22266 /// @sa https://json.nlohmann.me/api/basic_json/begin/ 22267 iterator begin() noexcept 22268 { 22269 iterator result(this); 22270 result.set_begin(); 22271 return result; 22272 } 22273 22274 /// @brief returns an iterator to the first element 22275 /// @sa https://json.nlohmann.me/api/basic_json/begin/ 22276 const_iterator begin() const noexcept 22277 { 22278 return cbegin(); 22279 } 22280 22281 /// @brief returns a const iterator to the first element 22282 /// @sa https://json.nlohmann.me/api/basic_json/cbegin/ 22283 const_iterator cbegin() const noexcept 22284 { 22285 const_iterator result(this); 22286 result.set_begin(); 22287 return result; 22288 } 22289 22290 /// @brief returns an iterator to one past the last element 22291 /// @sa https://json.nlohmann.me/api/basic_json/end/ 22292 iterator end() noexcept 22293 { 22294 iterator result(this); 22295 result.set_end(); 22296 return result; 22297 } 22298 22299 /// @brief returns an iterator to one past the last element 22300 /// @sa https://json.nlohmann.me/api/basic_json/end/ 22301 const_iterator end() const noexcept 22302 { 22303 return cend(); 22304 } 22305 22306 /// @brief returns an iterator to one past the last element 22307 /// @sa https://json.nlohmann.me/api/basic_json/cend/ 22308 const_iterator cend() const noexcept 22309 { 22310 const_iterator result(this); 22311 result.set_end(); 22312 return result; 22313 } 22314 22315 /// @brief returns an iterator to the reverse-beginning 22316 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/ 22317 reverse_iterator rbegin() noexcept 22318 { 22319 return reverse_iterator(end()); 22320 } 22321 22322 /// @brief returns an iterator to the reverse-beginning 22323 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/ 22324 const_reverse_iterator rbegin() const noexcept 22325 { 22326 return crbegin(); 22327 } 22328 22329 /// @brief returns an iterator to the reverse-end 22330 /// @sa https://json.nlohmann.me/api/basic_json/rend/ 22331 reverse_iterator rend() noexcept 22332 { 22333 return reverse_iterator(begin()); 22334 } 22335 22336 /// @brief returns an iterator to the reverse-end 22337 /// @sa https://json.nlohmann.me/api/basic_json/rend/ 22338 const_reverse_iterator rend() const noexcept 22339 { 22340 return crend(); 22341 } 22342 22343 /// @brief returns a const reverse iterator to the last element 22344 /// @sa https://json.nlohmann.me/api/basic_json/crbegin/ 22345 const_reverse_iterator crbegin() const noexcept 22346 { 22347 return const_reverse_iterator(cend()); 22348 } 22349 22350 /// @brief returns a const reverse iterator to one before the first 22351 /// @sa https://json.nlohmann.me/api/basic_json/crend/ 22352 const_reverse_iterator crend() const noexcept 22353 { 22354 return const_reverse_iterator(cbegin()); 22355 } 22356 22357 public: 22358 /// @brief wrapper to access iterator member functions in range-based for 22359 /// @sa https://json.nlohmann.me/api/basic_json/items/ 22360 /// @deprecated This function is deprecated since 3.1.0 and will be removed in 22361 /// version 4.0.0 of the library. Please use @ref items() instead; 22362 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`. 22363 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) 22364 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept 22365 { 22366 return ref.items(); 22367 } 22368 22369 /// @brief wrapper to access iterator member functions in range-based for 22370 /// @sa https://json.nlohmann.me/api/basic_json/items/ 22371 /// @deprecated This function is deprecated since 3.1.0 and will be removed in 22372 /// version 4.0.0 of the library. Please use @ref items() instead; 22373 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`. 22374 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) 22375 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept 22376 { 22377 return ref.items(); 22378 } 22379 22380 /// @brief helper to access iterator member functions in range-based for 22381 /// @sa https://json.nlohmann.me/api/basic_json/items/ 22382 iteration_proxy<iterator> items() noexcept 22383 { 22384 return iteration_proxy<iterator>(*this); 22385 } 22386 22387 /// @brief helper to access iterator member functions in range-based for 22388 /// @sa https://json.nlohmann.me/api/basic_json/items/ 22389 iteration_proxy<const_iterator> items() const noexcept 22390 { 22391 return iteration_proxy<const_iterator>(*this); 22392 } 22393 22394 /// @} 22395 22396 ////////////// 22397 // capacity // 22398 ////////////// 22399 22400 /// @name capacity 22401 /// @{ 22402 22403 /// @brief checks whether the container is empty. 22404 /// @sa https://json.nlohmann.me/api/basic_json/empty/ 22405 bool empty() const noexcept 22406 { 22407 switch (m_data.m_type) 22408 { 22409 case value_t::null: 22410 { 22411 // null values are empty 22412 return true; 22413 } 22414 22415 case value_t::array: 22416 { 22417 // delegate call to array_t::empty() 22418 return m_data.m_value.array->empty(); 22419 } 22420 22421 case value_t::object: 22422 { 22423 // delegate call to object_t::empty() 22424 return m_data.m_value.object->empty(); 22425 } 22426 22427 case value_t::string: 22428 case value_t::boolean: 22429 case value_t::number_integer: 22430 case value_t::number_unsigned: 22431 case value_t::number_float: 22432 case value_t::binary: 22433 case value_t::discarded: 22434 default: 22435 { 22436 // all other types are nonempty 22437 return false; 22438 } 22439 } 22440 } 22441 22442 /// @brief returns the number of elements 22443 /// @sa https://json.nlohmann.me/api/basic_json/size/ 22444 size_type size() const noexcept 22445 { 22446 switch (m_data.m_type) 22447 { 22448 case value_t::null: 22449 { 22450 // null values are empty 22451 return 0; 22452 } 22453 22454 case value_t::array: 22455 { 22456 // delegate call to array_t::size() 22457 return m_data.m_value.array->size(); 22458 } 22459 22460 case value_t::object: 22461 { 22462 // delegate call to object_t::size() 22463 return m_data.m_value.object->size(); 22464 } 22465 22466 case value_t::string: 22467 case value_t::boolean: 22468 case value_t::number_integer: 22469 case value_t::number_unsigned: 22470 case value_t::number_float: 22471 case value_t::binary: 22472 case value_t::discarded: 22473 default: 22474 { 22475 // all other types have size 1 22476 return 1; 22477 } 22478 } 22479 } 22480 22481 /// @brief returns the maximum possible number of elements 22482 /// @sa https://json.nlohmann.me/api/basic_json/max_size/ 22483 size_type max_size() const noexcept 22484 { 22485 switch (m_data.m_type) 22486 { 22487 case value_t::array: 22488 { 22489 // delegate call to array_t::max_size() 22490 return m_data.m_value.array->max_size(); 22491 } 22492 22493 case value_t::object: 22494 { 22495 // delegate call to object_t::max_size() 22496 return m_data.m_value.object->max_size(); 22497 } 22498 22499 case value_t::null: 22500 case value_t::string: 22501 case value_t::boolean: 22502 case value_t::number_integer: 22503 case value_t::number_unsigned: 22504 case value_t::number_float: 22505 case value_t::binary: 22506 case value_t::discarded: 22507 default: 22508 { 22509 // all other types have max_size() == size() 22510 return size(); 22511 } 22512 } 22513 } 22514 22515 /// @} 22516 22517 /////////////// 22518 // modifiers // 22519 /////////////// 22520 22521 /// @name modifiers 22522 /// @{ 22523 22524 /// @brief clears the contents 22525 /// @sa https://json.nlohmann.me/api/basic_json/clear/ 22526 void clear() noexcept 22527 { 22528 switch (m_data.m_type) 22529 { 22530 case value_t::number_integer: 22531 { 22532 m_data.m_value.number_integer = 0; 22533 break; 22534 } 22535 22536 case value_t::number_unsigned: 22537 { 22538 m_data.m_value.number_unsigned = 0; 22539 break; 22540 } 22541 22542 case value_t::number_float: 22543 { 22544 m_data.m_value.number_float = 0.0; 22545 break; 22546 } 22547 22548 case value_t::boolean: 22549 { 22550 m_data.m_value.boolean = false; 22551 break; 22552 } 22553 22554 case value_t::string: 22555 { 22556 m_data.m_value.string->clear(); 22557 break; 22558 } 22559 22560 case value_t::binary: 22561 { 22562 m_data.m_value.binary->clear(); 22563 break; 22564 } 22565 22566 case value_t::array: 22567 { 22568 m_data.m_value.array->clear(); 22569 break; 22570 } 22571 22572 case value_t::object: 22573 { 22574 m_data.m_value.object->clear(); 22575 break; 22576 } 22577 22578 case value_t::null: 22579 case value_t::discarded: 22580 default: 22581 break; 22582 } 22583 } 22584 22585 /// @brief add an object to an array 22586 /// @sa https://json.nlohmann.me/api/basic_json/push_back/ 22587 void push_back(basic_json&& val) 22588 { 22589 // push_back only works for null objects or arrays 22590 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) 22591 { 22592 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this)); 22593 } 22594 22595 // transform null object into an array 22596 if (is_null()) 22597 { 22598 m_data.m_type = value_t::array; 22599 m_data.m_value = value_t::array; 22600 assert_invariant(); 22601 } 22602 22603 // add element to array (move semantics) 22604 const auto old_capacity = m_data.m_value.array->capacity(); 22605 m_data.m_value.array->push_back(std::move(val)); 22606 set_parent(m_data.m_value.array->back(), old_capacity); 22607 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor 22608 } 22609 22610 /// @brief add an object to an array 22611 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 22612 reference operator+=(basic_json&& val) 22613 { 22614 push_back(std::move(val)); 22615 return *this; 22616 } 22617 22618 /// @brief add an object to an array 22619 /// @sa https://json.nlohmann.me/api/basic_json/push_back/ 22620 void push_back(const basic_json& val) 22621 { 22622 // push_back only works for null objects or arrays 22623 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) 22624 { 22625 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this)); 22626 } 22627 22628 // transform null object into an array 22629 if (is_null()) 22630 { 22631 m_data.m_type = value_t::array; 22632 m_data.m_value = value_t::array; 22633 assert_invariant(); 22634 } 22635 22636 // add element to array 22637 const auto old_capacity = m_data.m_value.array->capacity(); 22638 m_data.m_value.array->push_back(val); 22639 set_parent(m_data.m_value.array->back(), old_capacity); 22640 } 22641 22642 /// @brief add an object to an array 22643 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 22644 reference operator+=(const basic_json& val) 22645 { 22646 push_back(val); 22647 return *this; 22648 } 22649 22650 /// @brief add an object to an object 22651 /// @sa https://json.nlohmann.me/api/basic_json/push_back/ 22652 void push_back(const typename object_t::value_type& val) 22653 { 22654 // push_back only works for null objects or objects 22655 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) 22656 { 22657 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this)); 22658 } 22659 22660 // transform null object into an object 22661 if (is_null()) 22662 { 22663 m_data.m_type = value_t::object; 22664 m_data.m_value = value_t::object; 22665 assert_invariant(); 22666 } 22667 22668 // add element to object 22669 auto res = m_data.m_value.object->insert(val); 22670 set_parent(res.first->second); 22671 } 22672 22673 /// @brief add an object to an object 22674 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 22675 reference operator+=(const typename object_t::value_type& val) 22676 { 22677 push_back(val); 22678 return *this; 22679 } 22680 22681 /// @brief add an object to an object 22682 /// @sa https://json.nlohmann.me/api/basic_json/push_back/ 22683 void push_back(initializer_list_t init) 22684 { 22685 if (is_object() && init.size() == 2 && (*init.begin())->is_string()) 22686 { 22687 basic_json&& key = init.begin()->moved_or_copied(); 22688 push_back(typename object_t::value_type( 22689 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied())); 22690 } 22691 else 22692 { 22693 push_back(basic_json(init)); 22694 } 22695 } 22696 22697 /// @brief add an object to an object 22698 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 22699 reference operator+=(initializer_list_t init) 22700 { 22701 push_back(init); 22702 return *this; 22703 } 22704 22705 /// @brief add an object to an array 22706 /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/ 22707 template<class... Args> 22708 reference emplace_back(Args&& ... args) 22709 { 22710 // emplace_back only works for null objects or arrays 22711 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) 22712 { 22713 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this)); 22714 } 22715 22716 // transform null object into an array 22717 if (is_null()) 22718 { 22719 m_data.m_type = value_t::array; 22720 m_data.m_value = value_t::array; 22721 assert_invariant(); 22722 } 22723 22724 // add element to array (perfect forwarding) 22725 const auto old_capacity = m_data.m_value.array->capacity(); 22726 m_data.m_value.array->emplace_back(std::forward<Args>(args)...); 22727 return set_parent(m_data.m_value.array->back(), old_capacity); 22728 } 22729 22730 /// @brief add an object to an object if key does not exist 22731 /// @sa https://json.nlohmann.me/api/basic_json/emplace/ 22732 template<class... Args> 22733 std::pair<iterator, bool> emplace(Args&& ... args) 22734 { 22735 // emplace only works for null objects or arrays 22736 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) 22737 { 22738 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this)); 22739 } 22740 22741 // transform null object into an object 22742 if (is_null()) 22743 { 22744 m_data.m_type = value_t::object; 22745 m_data.m_value = value_t::object; 22746 assert_invariant(); 22747 } 22748 22749 // add element to array (perfect forwarding) 22750 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...); 22751 set_parent(res.first->second); 22752 22753 // create result iterator and set iterator to the result of emplace 22754 auto it = begin(); 22755 it.m_it.object_iterator = res.first; 22756 22757 // return pair of iterator and boolean 22758 return {it, res.second}; 22759 } 22760 22761 /// Helper for insertion of an iterator 22762 /// @note: This uses std::distance to support GCC 4.8, 22763 /// see https://github.com/nlohmann/json/pull/1257 22764 template<typename... Args> 22765 iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param) 22766 { 22767 iterator result(this); 22768 JSON_ASSERT(m_data.m_value.array != nullptr); 22769 22770 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator); 22771 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...); 22772 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos; 22773 22774 // This could have been written as: 22775 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val); 22776 // but the return value of insert is missing in GCC 4.8, so it is written this way instead. 22777 22778 set_parents(); 22779 return result; 22780 } 22781 22782 /// @brief inserts element into array 22783 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22784 iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param) 22785 { 22786 // insert only works for arrays 22787 if (JSON_HEDLEY_LIKELY(is_array())) 22788 { 22789 // check if iterator pos fits to this JSON value 22790 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) 22791 { 22792 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 22793 } 22794 22795 // insert to array and return iterator 22796 return insert_iterator(pos, val); 22797 } 22798 22799 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 22800 } 22801 22802 /// @brief inserts element into array 22803 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22804 iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param) 22805 { 22806 return insert(pos, val); 22807 } 22808 22809 /// @brief inserts copies of element into array 22810 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22811 iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param) 22812 { 22813 // insert only works for arrays 22814 if (JSON_HEDLEY_LIKELY(is_array())) 22815 { 22816 // check if iterator pos fits to this JSON value 22817 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) 22818 { 22819 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 22820 } 22821 22822 // insert to array and return iterator 22823 return insert_iterator(pos, cnt, val); 22824 } 22825 22826 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 22827 } 22828 22829 /// @brief inserts range of elements into array 22830 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22831 iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param) 22832 { 22833 // insert only works for arrays 22834 if (JSON_HEDLEY_UNLIKELY(!is_array())) 22835 { 22836 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 22837 } 22838 22839 // check if iterator pos fits to this JSON value 22840 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) 22841 { 22842 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 22843 } 22844 22845 // check if range iterators belong to the same JSON object 22846 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) 22847 { 22848 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this)); 22849 } 22850 22851 if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) 22852 { 22853 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this)); 22854 } 22855 22856 // insert to array and return iterator 22857 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); 22858 } 22859 22860 /// @brief inserts elements from initializer list into array 22861 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22862 iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param) 22863 { 22864 // insert only works for arrays 22865 if (JSON_HEDLEY_UNLIKELY(!is_array())) 22866 { 22867 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 22868 } 22869 22870 // check if iterator pos fits to this JSON value 22871 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) 22872 { 22873 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 22874 } 22875 22876 // insert to array and return iterator 22877 return insert_iterator(pos, ilist.begin(), ilist.end()); 22878 } 22879 22880 /// @brief inserts range of elements into object 22881 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22882 void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param) 22883 { 22884 // insert only works for objects 22885 if (JSON_HEDLEY_UNLIKELY(!is_object())) 22886 { 22887 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 22888 } 22889 22890 // check if range iterators belong to the same JSON object 22891 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) 22892 { 22893 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this)); 22894 } 22895 22896 // passed iterators must belong to objects 22897 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) 22898 { 22899 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this)); 22900 } 22901 22902 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); 22903 } 22904 22905 /// @brief updates a JSON object from another object, overwriting existing keys 22906 /// @sa https://json.nlohmann.me/api/basic_json/update/ 22907 void update(const_reference j, bool merge_objects = false) 22908 { 22909 update(j.begin(), j.end(), merge_objects); 22910 } 22911 22912 /// @brief updates a JSON object from another object, overwriting existing keys 22913 /// @sa https://json.nlohmann.me/api/basic_json/update/ 22914 void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param) 22915 { 22916 // implicitly convert null value to an empty object 22917 if (is_null()) 22918 { 22919 m_data.m_type = value_t::object; 22920 m_data.m_value.object = create<object_t>(); 22921 assert_invariant(); 22922 } 22923 22924 if (JSON_HEDLEY_UNLIKELY(!is_object())) 22925 { 22926 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this)); 22927 } 22928 22929 // check if range iterators belong to the same JSON object 22930 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) 22931 { 22932 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this)); 22933 } 22934 22935 // passed iterators must belong to objects 22936 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) 22937 { 22938 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object)); 22939 } 22940 22941 for (auto it = first; it != last; ++it) 22942 { 22943 if (merge_objects && it.value().is_object()) 22944 { 22945 auto it2 = m_data.m_value.object->find(it.key()); 22946 if (it2 != m_data.m_value.object->end()) 22947 { 22948 it2->second.update(it.value(), true); 22949 continue; 22950 } 22951 } 22952 m_data.m_value.object->operator[](it.key()) = it.value(); 22953 #if JSON_DIAGNOSTICS 22954 m_data.m_value.object->operator[](it.key()).m_parent = this; 22955 #endif 22956 } 22957 } 22958 22959 /// @brief exchanges the values 22960 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 22961 void swap(reference other) noexcept ( 22962 std::is_nothrow_move_constructible<value_t>::value&& 22963 std::is_nothrow_move_assignable<value_t>::value&& 22964 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 22965 std::is_nothrow_move_assignable<json_value>::value 22966 ) 22967 { 22968 std::swap(m_data.m_type, other.m_data.m_type); 22969 std::swap(m_data.m_value, other.m_data.m_value); 22970 22971 set_parents(); 22972 other.set_parents(); 22973 assert_invariant(); 22974 } 22975 22976 /// @brief exchanges the values 22977 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 22978 friend void swap(reference left, reference right) noexcept ( 22979 std::is_nothrow_move_constructible<value_t>::value&& 22980 std::is_nothrow_move_assignable<value_t>::value&& 22981 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 22982 std::is_nothrow_move_assignable<json_value>::value 22983 ) 22984 { 22985 left.swap(right); 22986 } 22987 22988 /// @brief exchanges the values 22989 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 22990 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 22991 { 22992 // swap only works for arrays 22993 if (JSON_HEDLEY_LIKELY(is_array())) 22994 { 22995 using std::swap; 22996 swap(*(m_data.m_value.array), other); 22997 } 22998 else 22999 { 23000 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this)); 23001 } 23002 } 23003 23004 /// @brief exchanges the values 23005 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 23006 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 23007 { 23008 // swap only works for objects 23009 if (JSON_HEDLEY_LIKELY(is_object())) 23010 { 23011 using std::swap; 23012 swap(*(m_data.m_value.object), other); 23013 } 23014 else 23015 { 23016 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this)); 23017 } 23018 } 23019 23020 /// @brief exchanges the values 23021 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 23022 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 23023 { 23024 // swap only works for strings 23025 if (JSON_HEDLEY_LIKELY(is_string())) 23026 { 23027 using std::swap; 23028 swap(*(m_data.m_value.string), other); 23029 } 23030 else 23031 { 23032 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this)); 23033 } 23034 } 23035 23036 /// @brief exchanges the values 23037 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 23038 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 23039 { 23040 // swap only works for strings 23041 if (JSON_HEDLEY_LIKELY(is_binary())) 23042 { 23043 using std::swap; 23044 swap(*(m_data.m_value.binary), other); 23045 } 23046 else 23047 { 23048 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this)); 23049 } 23050 } 23051 23052 /// @brief exchanges the values 23053 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 23054 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape) 23055 { 23056 // swap only works for strings 23057 if (JSON_HEDLEY_LIKELY(is_binary())) 23058 { 23059 using std::swap; 23060 swap(*(m_data.m_value.binary), other); 23061 } 23062 else 23063 { 23064 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this)); 23065 } 23066 } 23067 23068 /// @} 23069 23070 ////////////////////////////////////////// 23071 // lexicographical comparison operators // 23072 ////////////////////////////////////////// 23073 23074 /// @name lexicographical comparison operators 23075 /// @{ 23076 23077 // note parentheses around operands are necessary; see 23078 // https://github.com/nlohmann/json/issues/1530 23079 #define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \ 23080 const auto lhs_type = lhs.type(); \ 23081 const auto rhs_type = rhs.type(); \ 23082 \ 23083 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \ 23084 { \ 23085 switch (lhs_type) \ 23086 { \ 23087 case value_t::array: \ 23088 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \ 23089 \ 23090 case value_t::object: \ 23091 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \ 23092 \ 23093 case value_t::null: \ 23094 return (null_result); \ 23095 \ 23096 case value_t::string: \ 23097 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \ 23098 \ 23099 case value_t::boolean: \ 23100 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \ 23101 \ 23102 case value_t::number_integer: \ 23103 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \ 23104 \ 23105 case value_t::number_unsigned: \ 23106 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \ 23107 \ 23108 case value_t::number_float: \ 23109 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \ 23110 \ 23111 case value_t::binary: \ 23112 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \ 23113 \ 23114 case value_t::discarded: \ 23115 default: \ 23116 return (unordered_result); \ 23117 } \ 23118 } \ 23119 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \ 23120 { \ 23121 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \ 23122 } \ 23123 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \ 23124 { \ 23125 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \ 23126 } \ 23127 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \ 23128 { \ 23129 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \ 23130 } \ 23131 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \ 23132 { \ 23133 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \ 23134 } \ 23135 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \ 23136 { \ 23137 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \ 23138 } \ 23139 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \ 23140 { \ 23141 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \ 23142 } \ 23143 else if(compares_unordered(lhs, rhs))\ 23144 {\ 23145 return (unordered_result);\ 23146 }\ 23147 \ 23148 return (default_result); 23149 23150 JSON_PRIVATE_UNLESS_TESTED: 23151 // returns true if: 23152 // - any operand is NaN and the other operand is of number type 23153 // - any operand is discarded 23154 // in legacy mode, discarded values are considered ordered if 23155 // an operation is computed as an odd number of inverses of others 23156 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept 23157 { 23158 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number()) 23159 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number())) 23160 { 23161 return true; 23162 } 23163 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 23164 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse; 23165 #else 23166 static_cast<void>(inverse); 23167 return lhs.is_discarded() || rhs.is_discarded(); 23168 #endif 23169 } 23170 23171 private: 23172 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept 23173 { 23174 return compares_unordered(*this, rhs, inverse); 23175 } 23176 23177 public: 23178 #if JSON_HAS_THREE_WAY_COMPARISON 23179 /// @brief comparison: equal 23180 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 23181 bool operator==(const_reference rhs) const noexcept 23182 { 23183 #ifdef __GNUC__ 23184 #pragma GCC diagnostic push 23185 #pragma GCC diagnostic ignored "-Wfloat-equal" 23186 #endif 23187 const_reference lhs = *this; 23188 JSON_IMPLEMENT_OPERATOR( ==, true, false, false) 23189 #ifdef __GNUC__ 23190 #pragma GCC diagnostic pop 23191 #endif 23192 } 23193 23194 /// @brief comparison: equal 23195 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 23196 template<typename ScalarType> 23197 requires std::is_scalar_v<ScalarType> 23198 bool operator==(ScalarType rhs) const noexcept 23199 { 23200 return *this == basic_json(rhs); 23201 } 23202 23203 /// @brief comparison: not equal 23204 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 23205 bool operator!=(const_reference rhs) const noexcept 23206 { 23207 if (compares_unordered(rhs, true)) 23208 { 23209 return false; 23210 } 23211 return !operator==(rhs); 23212 } 23213 23214 /// @brief comparison: 3-way 23215 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/ 23216 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD* 23217 { 23218 const_reference lhs = *this; 23219 // default_result is used if we cannot compare values. In that case, 23220 // we compare types. 23221 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD* 23222 std::partial_ordering::equivalent, 23223 std::partial_ordering::unordered, 23224 lhs_type <=> rhs_type) // *NOPAD* 23225 } 23226 23227 /// @brief comparison: 3-way 23228 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/ 23229 template<typename ScalarType> 23230 requires std::is_scalar_v<ScalarType> 23231 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD* 23232 { 23233 return *this <=> basic_json(rhs); // *NOPAD* 23234 } 23235 23236 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 23237 // all operators that are computed as an odd number of inverses of others 23238 // need to be overloaded to emulate the legacy comparison behavior 23239 23240 /// @brief comparison: less than or equal 23241 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23242 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON) 23243 bool operator<=(const_reference rhs) const noexcept 23244 { 23245 if (compares_unordered(rhs, true)) 23246 { 23247 return false; 23248 } 23249 return !(rhs < *this); 23250 } 23251 23252 /// @brief comparison: less than or equal 23253 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23254 template<typename ScalarType> 23255 requires std::is_scalar_v<ScalarType> 23256 bool operator<=(ScalarType rhs) const noexcept 23257 { 23258 return *this <= basic_json(rhs); 23259 } 23260 23261 /// @brief comparison: greater than or equal 23262 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23263 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON) 23264 bool operator>=(const_reference rhs) const noexcept 23265 { 23266 if (compares_unordered(rhs, true)) 23267 { 23268 return false; 23269 } 23270 return !(*this < rhs); 23271 } 23272 23273 /// @brief comparison: greater than or equal 23274 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23275 template<typename ScalarType> 23276 requires std::is_scalar_v<ScalarType> 23277 bool operator>=(ScalarType rhs) const noexcept 23278 { 23279 return *this >= basic_json(rhs); 23280 } 23281 #endif 23282 #else 23283 /// @brief comparison: equal 23284 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 23285 friend bool operator==(const_reference lhs, const_reference rhs) noexcept 23286 { 23287 #ifdef __GNUC__ 23288 #pragma GCC diagnostic push 23289 #pragma GCC diagnostic ignored "-Wfloat-equal" 23290 #endif 23291 JSON_IMPLEMENT_OPERATOR( ==, true, false, false) 23292 #ifdef __GNUC__ 23293 #pragma GCC diagnostic pop 23294 #endif 23295 } 23296 23297 /// @brief comparison: equal 23298 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 23299 template<typename ScalarType, typename std::enable_if< 23300 std::is_scalar<ScalarType>::value, int>::type = 0> 23301 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept 23302 { 23303 return lhs == basic_json(rhs); 23304 } 23305 23306 /// @brief comparison: equal 23307 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 23308 template<typename ScalarType, typename std::enable_if< 23309 std::is_scalar<ScalarType>::value, int>::type = 0> 23310 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept 23311 { 23312 return basic_json(lhs) == rhs; 23313 } 23314 23315 /// @brief comparison: not equal 23316 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 23317 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept 23318 { 23319 if (compares_unordered(lhs, rhs, true)) 23320 { 23321 return false; 23322 } 23323 return !(lhs == rhs); 23324 } 23325 23326 /// @brief comparison: not equal 23327 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 23328 template<typename ScalarType, typename std::enable_if< 23329 std::is_scalar<ScalarType>::value, int>::type = 0> 23330 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept 23331 { 23332 return lhs != basic_json(rhs); 23333 } 23334 23335 /// @brief comparison: not equal 23336 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 23337 template<typename ScalarType, typename std::enable_if< 23338 std::is_scalar<ScalarType>::value, int>::type = 0> 23339 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept 23340 { 23341 return basic_json(lhs) != rhs; 23342 } 23343 23344 /// @brief comparison: less than 23345 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ 23346 friend bool operator<(const_reference lhs, const_reference rhs) noexcept 23347 { 23348 // default_result is used if we cannot compare values. In that case, 23349 // we compare types. Note we have to call the operator explicitly, 23350 // because MSVC has problems otherwise. 23351 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type)) 23352 } 23353 23354 /// @brief comparison: less than 23355 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ 23356 template<typename ScalarType, typename std::enable_if< 23357 std::is_scalar<ScalarType>::value, int>::type = 0> 23358 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept 23359 { 23360 return lhs < basic_json(rhs); 23361 } 23362 23363 /// @brief comparison: less than 23364 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ 23365 template<typename ScalarType, typename std::enable_if< 23366 std::is_scalar<ScalarType>::value, int>::type = 0> 23367 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept 23368 { 23369 return basic_json(lhs) < rhs; 23370 } 23371 23372 /// @brief comparison: less than or equal 23373 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23374 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept 23375 { 23376 if (compares_unordered(lhs, rhs, true)) 23377 { 23378 return false; 23379 } 23380 return !(rhs < lhs); 23381 } 23382 23383 /// @brief comparison: less than or equal 23384 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23385 template<typename ScalarType, typename std::enable_if< 23386 std::is_scalar<ScalarType>::value, int>::type = 0> 23387 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept 23388 { 23389 return lhs <= basic_json(rhs); 23390 } 23391 23392 /// @brief comparison: less than or equal 23393 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23394 template<typename ScalarType, typename std::enable_if< 23395 std::is_scalar<ScalarType>::value, int>::type = 0> 23396 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept 23397 { 23398 return basic_json(lhs) <= rhs; 23399 } 23400 23401 /// @brief comparison: greater than 23402 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ 23403 friend bool operator>(const_reference lhs, const_reference rhs) noexcept 23404 { 23405 // double inverse 23406 if (compares_unordered(lhs, rhs)) 23407 { 23408 return false; 23409 } 23410 return !(lhs <= rhs); 23411 } 23412 23413 /// @brief comparison: greater than 23414 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ 23415 template<typename ScalarType, typename std::enable_if< 23416 std::is_scalar<ScalarType>::value, int>::type = 0> 23417 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept 23418 { 23419 return lhs > basic_json(rhs); 23420 } 23421 23422 /// @brief comparison: greater than 23423 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ 23424 template<typename ScalarType, typename std::enable_if< 23425 std::is_scalar<ScalarType>::value, int>::type = 0> 23426 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept 23427 { 23428 return basic_json(lhs) > rhs; 23429 } 23430 23431 /// @brief comparison: greater than or equal 23432 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23433 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept 23434 { 23435 if (compares_unordered(lhs, rhs, true)) 23436 { 23437 return false; 23438 } 23439 return !(lhs < rhs); 23440 } 23441 23442 /// @brief comparison: greater than or equal 23443 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23444 template<typename ScalarType, typename std::enable_if< 23445 std::is_scalar<ScalarType>::value, int>::type = 0> 23446 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept 23447 { 23448 return lhs >= basic_json(rhs); 23449 } 23450 23451 /// @brief comparison: greater than or equal 23452 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23453 template<typename ScalarType, typename std::enable_if< 23454 std::is_scalar<ScalarType>::value, int>::type = 0> 23455 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept 23456 { 23457 return basic_json(lhs) >= rhs; 23458 } 23459 #endif 23460 23461 #undef JSON_IMPLEMENT_OPERATOR 23462 23463 /// @} 23464 23465 /////////////////// 23466 // serialization // 23467 /////////////////// 23468 23469 /// @name serialization 23470 /// @{ 23471 #ifndef JSON_NO_IO 23472 /// @brief serialize to stream 23473 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ 23474 friend std::ostream& operator<<(std::ostream& o, const basic_json& j) 23475 { 23476 // read width member and use it as indentation parameter if nonzero 23477 const bool pretty_print = o.width() > 0; 23478 const auto indentation = pretty_print ? o.width() : 0; 23479 23480 // reset width to 0 for subsequent calls to this stream 23481 o.width(0); 23482 23483 // do the actual serialization 23484 serializer s(detail::output_adapter<char>(o), o.fill()); 23485 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation)); 23486 return o; 23487 } 23488 23489 /// @brief serialize to stream 23490 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ 23491 /// @deprecated This function is deprecated since 3.0.0 and will be removed in 23492 /// version 4.0.0 of the library. Please use 23493 /// operator<<(std::ostream&, const basic_json&) instead; that is, 23494 /// replace calls like `j >> o;` with `o << j;`. 23495 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&)) 23496 friend std::ostream& operator>>(const basic_json& j, std::ostream& o) 23497 { 23498 return o << j; 23499 } 23500 #endif // JSON_NO_IO 23501 /// @} 23502 23503 ///////////////////// 23504 // deserialization // 23505 ///////////////////// 23506 23507 /// @name deserialization 23508 /// @{ 23509 23510 /// @brief deserialize from a compatible input 23511 /// @sa https://json.nlohmann.me/api/basic_json/parse/ 23512 template<typename InputType> 23513 JSON_HEDLEY_WARN_UNUSED_RESULT 23514 static basic_json parse(InputType&& i, 23515 parser_callback_t cb = nullptr, 23516 const bool allow_exceptions = true, 23517 const bool ignore_comments = false) 23518 { 23519 basic_json result; 23520 parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); 23521 return result; 23522 } 23523 23524 /// @brief deserialize from a pair of character iterators 23525 /// @sa https://json.nlohmann.me/api/basic_json/parse/ 23526 template<typename IteratorType> 23527 JSON_HEDLEY_WARN_UNUSED_RESULT 23528 static basic_json parse(IteratorType first, 23529 IteratorType last, 23530 parser_callback_t cb = nullptr, 23531 const bool allow_exceptions = true, 23532 const bool ignore_comments = false) 23533 { 23534 basic_json result; 23535 parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); 23536 return result; 23537 } 23538 23539 JSON_HEDLEY_WARN_UNUSED_RESULT 23540 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) 23541 static basic_json parse(detail::span_input_adapter&& i, 23542 parser_callback_t cb = nullptr, 23543 const bool allow_exceptions = true, 23544 const bool ignore_comments = false) 23545 { 23546 basic_json result; 23547 parser(i.get(), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); 23548 return result; 23549 } 23550 23551 /// @brief check if the input is valid JSON 23552 /// @sa https://json.nlohmann.me/api/basic_json/accept/ 23553 template<typename InputType> 23554 static bool accept(InputType&& i, 23555 const bool ignore_comments = false) 23556 { 23557 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true); 23558 } 23559 23560 /// @brief check if the input is valid JSON 23561 /// @sa https://json.nlohmann.me/api/basic_json/accept/ 23562 template<typename IteratorType> 23563 static bool accept(IteratorType first, IteratorType last, 23564 const bool ignore_comments = false) 23565 { 23566 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true); 23567 } 23568 23569 JSON_HEDLEY_WARN_UNUSED_RESULT 23570 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len)) 23571 static bool accept(detail::span_input_adapter&& i, 23572 const bool ignore_comments = false) 23573 { 23574 return parser(i.get(), nullptr, false, ignore_comments).accept(true); 23575 } 23576 23577 /// @brief generate SAX events 23578 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ 23579 template <typename InputType, typename SAX> 23580 JSON_HEDLEY_NON_NULL(2) 23581 static bool sax_parse(InputType&& i, SAX* sax, 23582 input_format_t format = input_format_t::json, 23583 const bool strict = true, 23584 const bool ignore_comments = false) 23585 { 23586 auto ia = detail::input_adapter(std::forward<InputType>(i)); 23587 return format == input_format_t::json 23588 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) 23589 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict); 23590 } 23591 23592 /// @brief generate SAX events 23593 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ 23594 template<class IteratorType, class SAX> 23595 JSON_HEDLEY_NON_NULL(3) 23596 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax, 23597 input_format_t format = input_format_t::json, 23598 const bool strict = true, 23599 const bool ignore_comments = false) 23600 { 23601 auto ia = detail::input_adapter(std::move(first), std::move(last)); 23602 return format == input_format_t::json 23603 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) 23604 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict); 23605 } 23606 23607 /// @brief generate SAX events 23608 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ 23609 /// @deprecated This function is deprecated since 3.8.0 and will be removed in 23610 /// version 4.0.0 of the library. Please use 23611 /// sax_parse(ptr, ptr + len) instead. 23612 template <typename SAX> 23613 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...)) 23614 JSON_HEDLEY_NON_NULL(2) 23615 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax, 23616 input_format_t format = input_format_t::json, 23617 const bool strict = true, 23618 const bool ignore_comments = false) 23619 { 23620 auto ia = i.get(); 23621 return format == input_format_t::json 23622 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 23623 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) 23624 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 23625 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict); 23626 } 23627 #ifndef JSON_NO_IO 23628 /// @brief deserialize from stream 23629 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/ 23630 /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in 23631 /// version 4.0.0 of the library. Please use 23632 /// operator>>(std::istream&, basic_json&) instead; that is, 23633 /// replace calls like `j << i;` with `i >> j;`. 23634 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&)) 23635 friend std::istream& operator<<(basic_json& j, std::istream& i) 23636 { 23637 return operator>>(i, j); 23638 } 23639 23640 /// @brief deserialize from stream 23641 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/ 23642 friend std::istream& operator>>(std::istream& i, basic_json& j) 23643 { 23644 parser(detail::input_adapter(i)).parse(false, j); 23645 return i; 23646 } 23647 #endif // JSON_NO_IO 23648 /// @} 23649 23650 /////////////////////////// 23651 // convenience functions // 23652 /////////////////////////// 23653 23654 /// @brief return the type as string 23655 /// @sa https://json.nlohmann.me/api/basic_json/type_name/ 23656 JSON_HEDLEY_RETURNS_NON_NULL 23657 const char* type_name() const noexcept 23658 { 23659 switch (m_data.m_type) 23660 { 23661 case value_t::null: 23662 return "null"; 23663 case value_t::object: 23664 return "object"; 23665 case value_t::array: 23666 return "array"; 23667 case value_t::string: 23668 return "string"; 23669 case value_t::boolean: 23670 return "boolean"; 23671 case value_t::binary: 23672 return "binary"; 23673 case value_t::discarded: 23674 return "discarded"; 23675 case value_t::number_integer: 23676 case value_t::number_unsigned: 23677 case value_t::number_float: 23678 default: 23679 return "number"; 23680 } 23681 } 23682 23683 JSON_PRIVATE_UNLESS_TESTED: 23684 ////////////////////// 23685 // member variables // 23686 ////////////////////// 23687 23688 struct data 23689 { 23690 /// the type of the current element 23691 value_t m_type = value_t::null; 23692 23693 /// the value of the current element 23694 json_value m_value = {}; 23695 23696 data(const value_t v) 23697 : m_type(v), m_value(v) 23698 { 23699 } 23700 23701 data(size_type cnt, const basic_json& val) 23702 : m_type(value_t::array) 23703 { 23704 m_value.array = create<array_t>(cnt, val); 23705 } 23706 23707 data() noexcept = default; 23708 data(data&&) noexcept = default; 23709 data(const data&) noexcept = delete; 23710 data& operator=(data&&) noexcept = delete; 23711 data& operator=(const data&) noexcept = delete; 23712 23713 ~data() noexcept 23714 { 23715 m_value.destroy(m_type); 23716 } 23717 }; 23718 23719 data m_data = {}; 23720 23721 #if JSON_DIAGNOSTICS 23722 /// a pointer to a parent value (for debugging purposes) 23723 basic_json* m_parent = nullptr; 23724 #endif 23725 23726 ////////////////////////////////////////// 23727 // binary serialization/deserialization // 23728 ////////////////////////////////////////// 23729 23730 /// @name binary serialization/deserialization support 23731 /// @{ 23732 23733 public: 23734 /// @brief create a CBOR serialization of a given JSON value 23735 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ 23736 static std::vector<std::uint8_t> to_cbor(const basic_json& j) 23737 { 23738 std::vector<std::uint8_t> result; 23739 to_cbor(j, result); 23740 return result; 23741 } 23742 23743 /// @brief create a CBOR serialization of a given JSON value 23744 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ 23745 static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o) 23746 { 23747 binary_writer<std::uint8_t>(o).write_cbor(j); 23748 } 23749 23750 /// @brief create a CBOR serialization of a given JSON value 23751 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ 23752 static void to_cbor(const basic_json& j, detail::output_adapter<char> o) 23753 { 23754 binary_writer<char>(o).write_cbor(j); 23755 } 23756 23757 /// @brief create a MessagePack serialization of a given JSON value 23758 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ 23759 static std::vector<std::uint8_t> to_msgpack(const basic_json& j) 23760 { 23761 std::vector<std::uint8_t> result; 23762 to_msgpack(j, result); 23763 return result; 23764 } 23765 23766 /// @brief create a MessagePack serialization of a given JSON value 23767 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ 23768 static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o) 23769 { 23770 binary_writer<std::uint8_t>(o).write_msgpack(j); 23771 } 23772 23773 /// @brief create a MessagePack serialization of a given JSON value 23774 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ 23775 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o) 23776 { 23777 binary_writer<char>(o).write_msgpack(j); 23778 } 23779 23780 /// @brief create a UBJSON serialization of a given JSON value 23781 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ 23782 static std::vector<std::uint8_t> to_ubjson(const basic_json& j, 23783 const bool use_size = false, 23784 const bool use_type = false) 23785 { 23786 std::vector<std::uint8_t> result; 23787 to_ubjson(j, result, use_size, use_type); 23788 return result; 23789 } 23790 23791 /// @brief create a UBJSON serialization of a given JSON value 23792 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ 23793 static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o, 23794 const bool use_size = false, const bool use_type = false) 23795 { 23796 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type); 23797 } 23798 23799 /// @brief create a UBJSON serialization of a given JSON value 23800 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ 23801 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o, 23802 const bool use_size = false, const bool use_type = false) 23803 { 23804 binary_writer<char>(o).write_ubjson(j, use_size, use_type); 23805 } 23806 23807 /// @brief create a BJData serialization of a given JSON value 23808 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ 23809 static std::vector<std::uint8_t> to_bjdata(const basic_json& j, 23810 const bool use_size = false, 23811 const bool use_type = false) 23812 { 23813 std::vector<std::uint8_t> result; 23814 to_bjdata(j, result, use_size, use_type); 23815 return result; 23816 } 23817 23818 /// @brief create a BJData serialization of a given JSON value 23819 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ 23820 static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o, 23821 const bool use_size = false, const bool use_type = false) 23822 { 23823 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true); 23824 } 23825 23826 /// @brief create a BJData serialization of a given JSON value 23827 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ 23828 static void to_bjdata(const basic_json& j, detail::output_adapter<char> o, 23829 const bool use_size = false, const bool use_type = false) 23830 { 23831 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true); 23832 } 23833 23834 /// @brief create a BSON serialization of a given JSON value 23835 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ 23836 static std::vector<std::uint8_t> to_bson(const basic_json& j) 23837 { 23838 std::vector<std::uint8_t> result; 23839 to_bson(j, result); 23840 return result; 23841 } 23842 23843 /// @brief create a BSON serialization of a given JSON value 23844 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ 23845 static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o) 23846 { 23847 binary_writer<std::uint8_t>(o).write_bson(j); 23848 } 23849 23850 /// @brief create a BSON serialization of a given JSON value 23851 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ 23852 static void to_bson(const basic_json& j, detail::output_adapter<char> o) 23853 { 23854 binary_writer<char>(o).write_bson(j); 23855 } 23856 23857 /// @brief create a JSON value from an input in CBOR format 23858 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/ 23859 template<typename InputType> 23860 JSON_HEDLEY_WARN_UNUSED_RESULT 23861 static basic_json from_cbor(InputType&& i, 23862 const bool strict = true, 23863 const bool allow_exceptions = true, 23864 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 23865 { 23866 basic_json result; 23867 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23868 auto ia = detail::input_adapter(std::forward<InputType>(i)); 23869 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); 23870 return res ? result : basic_json(value_t::discarded); 23871 } 23872 23873 /// @brief create a JSON value from an input in CBOR format 23874 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/ 23875 template<typename IteratorType> 23876 JSON_HEDLEY_WARN_UNUSED_RESULT 23877 static basic_json from_cbor(IteratorType first, IteratorType last, 23878 const bool strict = true, 23879 const bool allow_exceptions = true, 23880 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 23881 { 23882 basic_json result; 23883 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23884 auto ia = detail::input_adapter(std::move(first), std::move(last)); 23885 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); 23886 return res ? result : basic_json(value_t::discarded); 23887 } 23888 23889 template<typename T> 23890 JSON_HEDLEY_WARN_UNUSED_RESULT 23891 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) 23892 static basic_json from_cbor(const T* ptr, std::size_t len, 23893 const bool strict = true, 23894 const bool allow_exceptions = true, 23895 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 23896 { 23897 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); 23898 } 23899 23900 JSON_HEDLEY_WARN_UNUSED_RESULT 23901 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) 23902 static basic_json from_cbor(detail::span_input_adapter&& i, 23903 const bool strict = true, 23904 const bool allow_exceptions = true, 23905 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 23906 { 23907 basic_json result; 23908 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23909 auto ia = i.get(); 23910 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 23911 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); 23912 return res ? result : basic_json(value_t::discarded); 23913 } 23914 23915 /// @brief create a JSON value from an input in MessagePack format 23916 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ 23917 template<typename InputType> 23918 JSON_HEDLEY_WARN_UNUSED_RESULT 23919 static basic_json from_msgpack(InputType&& i, 23920 const bool strict = true, 23921 const bool allow_exceptions = true) 23922 { 23923 basic_json result; 23924 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23925 auto ia = detail::input_adapter(std::forward<InputType>(i)); 23926 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); 23927 return res ? result : basic_json(value_t::discarded); 23928 } 23929 23930 /// @brief create a JSON value from an input in MessagePack format 23931 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ 23932 template<typename IteratorType> 23933 JSON_HEDLEY_WARN_UNUSED_RESULT 23934 static basic_json from_msgpack(IteratorType first, IteratorType last, 23935 const bool strict = true, 23936 const bool allow_exceptions = true) 23937 { 23938 basic_json result; 23939 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23940 auto ia = detail::input_adapter(std::move(first), std::move(last)); 23941 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); 23942 return res ? result : basic_json(value_t::discarded); 23943 } 23944 23945 template<typename T> 23946 JSON_HEDLEY_WARN_UNUSED_RESULT 23947 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) 23948 static basic_json from_msgpack(const T* ptr, std::size_t len, 23949 const bool strict = true, 23950 const bool allow_exceptions = true) 23951 { 23952 return from_msgpack(ptr, ptr + len, strict, allow_exceptions); 23953 } 23954 23955 JSON_HEDLEY_WARN_UNUSED_RESULT 23956 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) 23957 static basic_json from_msgpack(detail::span_input_adapter&& i, 23958 const bool strict = true, 23959 const bool allow_exceptions = true) 23960 { 23961 basic_json result; 23962 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23963 auto ia = i.get(); 23964 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 23965 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); 23966 return res ? result : basic_json(value_t::discarded); 23967 } 23968 23969 /// @brief create a JSON value from an input in UBJSON format 23970 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ 23971 template<typename InputType> 23972 JSON_HEDLEY_WARN_UNUSED_RESULT 23973 static basic_json from_ubjson(InputType&& i, 23974 const bool strict = true, 23975 const bool allow_exceptions = true) 23976 { 23977 basic_json result; 23978 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23979 auto ia = detail::input_adapter(std::forward<InputType>(i)); 23980 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); 23981 return res ? result : basic_json(value_t::discarded); 23982 } 23983 23984 /// @brief create a JSON value from an input in UBJSON format 23985 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ 23986 template<typename IteratorType> 23987 JSON_HEDLEY_WARN_UNUSED_RESULT 23988 static basic_json from_ubjson(IteratorType first, IteratorType last, 23989 const bool strict = true, 23990 const bool allow_exceptions = true) 23991 { 23992 basic_json result; 23993 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23994 auto ia = detail::input_adapter(std::move(first), std::move(last)); 23995 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); 23996 return res ? result : basic_json(value_t::discarded); 23997 } 23998 23999 template<typename T> 24000 JSON_HEDLEY_WARN_UNUSED_RESULT 24001 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) 24002 static basic_json from_ubjson(const T* ptr, std::size_t len, 24003 const bool strict = true, 24004 const bool allow_exceptions = true) 24005 { 24006 return from_ubjson(ptr, ptr + len, strict, allow_exceptions); 24007 } 24008 24009 JSON_HEDLEY_WARN_UNUSED_RESULT 24010 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) 24011 static basic_json from_ubjson(detail::span_input_adapter&& i, 24012 const bool strict = true, 24013 const bool allow_exceptions = true) 24014 { 24015 basic_json result; 24016 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 24017 auto ia = i.get(); 24018 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 24019 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); 24020 return res ? result : basic_json(value_t::discarded); 24021 } 24022 24023 /// @brief create a JSON value from an input in BJData format 24024 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/ 24025 template<typename InputType> 24026 JSON_HEDLEY_WARN_UNUSED_RESULT 24027 static basic_json from_bjdata(InputType&& i, 24028 const bool strict = true, 24029 const bool allow_exceptions = true) 24030 { 24031 basic_json result; 24032 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 24033 auto ia = detail::input_adapter(std::forward<InputType>(i)); 24034 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); 24035 return res ? result : basic_json(value_t::discarded); 24036 } 24037 24038 /// @brief create a JSON value from an input in BJData format 24039 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/ 24040 template<typename IteratorType> 24041 JSON_HEDLEY_WARN_UNUSED_RESULT 24042 static basic_json from_bjdata(IteratorType first, IteratorType last, 24043 const bool strict = true, 24044 const bool allow_exceptions = true) 24045 { 24046 basic_json result; 24047 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 24048 auto ia = detail::input_adapter(std::move(first), std::move(last)); 24049 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); 24050 return res ? result : basic_json(value_t::discarded); 24051 } 24052 24053 /// @brief create a JSON value from an input in BSON format 24054 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ 24055 template<typename InputType> 24056 JSON_HEDLEY_WARN_UNUSED_RESULT 24057 static basic_json from_bson(InputType&& i, 24058 const bool strict = true, 24059 const bool allow_exceptions = true) 24060 { 24061 basic_json result; 24062 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 24063 auto ia = detail::input_adapter(std::forward<InputType>(i)); 24064 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); 24065 return res ? result : basic_json(value_t::discarded); 24066 } 24067 24068 /// @brief create a JSON value from an input in BSON format 24069 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ 24070 template<typename IteratorType> 24071 JSON_HEDLEY_WARN_UNUSED_RESULT 24072 static basic_json from_bson(IteratorType first, IteratorType last, 24073 const bool strict = true, 24074 const bool allow_exceptions = true) 24075 { 24076 basic_json result; 24077 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 24078 auto ia = detail::input_adapter(std::move(first), std::move(last)); 24079 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); 24080 return res ? result : basic_json(value_t::discarded); 24081 } 24082 24083 template<typename T> 24084 JSON_HEDLEY_WARN_UNUSED_RESULT 24085 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) 24086 static basic_json from_bson(const T* ptr, std::size_t len, 24087 const bool strict = true, 24088 const bool allow_exceptions = true) 24089 { 24090 return from_bson(ptr, ptr + len, strict, allow_exceptions); 24091 } 24092 24093 JSON_HEDLEY_WARN_UNUSED_RESULT 24094 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) 24095 static basic_json from_bson(detail::span_input_adapter&& i, 24096 const bool strict = true, 24097 const bool allow_exceptions = true) 24098 { 24099 basic_json result; 24100 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 24101 auto ia = i.get(); 24102 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 24103 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); 24104 return res ? result : basic_json(value_t::discarded); 24105 } 24106 /// @} 24107 24108 ////////////////////////// 24109 // JSON Pointer support // 24110 ////////////////////////// 24111 24112 /// @name JSON Pointer functions 24113 /// @{ 24114 24115 /// @brief access specified element via JSON Pointer 24116 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 24117 reference operator[](const json_pointer& ptr) 24118 { 24119 return ptr.get_unchecked(this); 24120 } 24121 24122 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 24123 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 24124 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) 24125 { 24126 return ptr.get_unchecked(this); 24127 } 24128 24129 /// @brief access specified element via JSON Pointer 24130 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 24131 const_reference operator[](const json_pointer& ptr) const 24132 { 24133 return ptr.get_unchecked(this); 24134 } 24135 24136 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 24137 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 24138 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const 24139 { 24140 return ptr.get_unchecked(this); 24141 } 24142 24143 /// @brief access specified element via JSON Pointer 24144 /// @sa https://json.nlohmann.me/api/basic_json/at/ 24145 reference at(const json_pointer& ptr) 24146 { 24147 return ptr.get_checked(this); 24148 } 24149 24150 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 24151 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 24152 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) 24153 { 24154 return ptr.get_checked(this); 24155 } 24156 24157 /// @brief access specified element via JSON Pointer 24158 /// @sa https://json.nlohmann.me/api/basic_json/at/ 24159 const_reference at(const json_pointer& ptr) const 24160 { 24161 return ptr.get_checked(this); 24162 } 24163 24164 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 24165 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 24166 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const 24167 { 24168 return ptr.get_checked(this); 24169 } 24170 24171 /// @brief return flattened JSON value 24172 /// @sa https://json.nlohmann.me/api/basic_json/flatten/ 24173 basic_json flatten() const 24174 { 24175 basic_json result(value_t::object); 24176 json_pointer::flatten("", *this, result); 24177 return result; 24178 } 24179 24180 /// @brief unflatten a previously flattened JSON value 24181 /// @sa https://json.nlohmann.me/api/basic_json/unflatten/ 24182 basic_json unflatten() const 24183 { 24184 return json_pointer::unflatten(*this); 24185 } 24186 24187 /// @} 24188 24189 ////////////////////////// 24190 // JSON Patch functions // 24191 ////////////////////////// 24192 24193 /// @name JSON Patch functions 24194 /// @{ 24195 24196 /// @brief applies a JSON patch in-place without copying the object 24197 /// @sa https://json.nlohmann.me/api/basic_json/patch/ 24198 void patch_inplace(const basic_json& json_patch) 24199 { 24200 basic_json& result = *this; 24201 // the valid JSON Patch operations 24202 enum class patch_operations {add, remove, replace, move, copy, test, invalid}; 24203 24204 const auto get_op = [](const std::string & op) 24205 { 24206 if (op == "add") 24207 { 24208 return patch_operations::add; 24209 } 24210 if (op == "remove") 24211 { 24212 return patch_operations::remove; 24213 } 24214 if (op == "replace") 24215 { 24216 return patch_operations::replace; 24217 } 24218 if (op == "move") 24219 { 24220 return patch_operations::move; 24221 } 24222 if (op == "copy") 24223 { 24224 return patch_operations::copy; 24225 } 24226 if (op == "test") 24227 { 24228 return patch_operations::test; 24229 } 24230 24231 return patch_operations::invalid; 24232 }; 24233 24234 // wrapper for "add" operation; add value at ptr 24235 const auto operation_add = [&result](json_pointer & ptr, const basic_json & val) 24236 { 24237 // adding to the root of the target document means replacing it 24238 if (ptr.empty()) 24239 { 24240 result = val; 24241 return; 24242 } 24243 24244 // make sure the top element of the pointer exists 24245 json_pointer const top_pointer = ptr.top(); 24246 if (top_pointer != ptr) 24247 { 24248 result.at(top_pointer); 24249 } 24250 24251 // get reference to parent of JSON pointer ptr 24252 const auto last_path = ptr.back(); 24253 ptr.pop_back(); 24254 // parent must exist when performing patch add per RFC6902 specs 24255 basic_json& parent = result.at(ptr); 24256 24257 switch (parent.m_data.m_type) 24258 { 24259 case value_t::null: 24260 case value_t::object: 24261 { 24262 // use operator[] to add value 24263 parent[last_path] = val; 24264 break; 24265 } 24266 24267 case value_t::array: 24268 { 24269 if (last_path == "-") 24270 { 24271 // special case: append to back 24272 parent.push_back(val); 24273 } 24274 else 24275 { 24276 const auto idx = json_pointer::template array_index<basic_json_t>(last_path); 24277 if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) 24278 { 24279 // avoid undefined behavior 24280 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent)); 24281 } 24282 24283 // default case: insert add offset 24284 parent.insert(parent.begin() + static_cast<difference_type>(idx), val); 24285 } 24286 break; 24287 } 24288 24289 // if there exists a parent it cannot be primitive 24290 case value_t::string: // LCOV_EXCL_LINE 24291 case value_t::boolean: // LCOV_EXCL_LINE 24292 case value_t::number_integer: // LCOV_EXCL_LINE 24293 case value_t::number_unsigned: // LCOV_EXCL_LINE 24294 case value_t::number_float: // LCOV_EXCL_LINE 24295 case value_t::binary: // LCOV_EXCL_LINE 24296 case value_t::discarded: // LCOV_EXCL_LINE 24297 default: // LCOV_EXCL_LINE 24298 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 24299 } 24300 }; 24301 24302 // wrapper for "remove" operation; remove value at ptr 24303 const auto operation_remove = [this, & result](json_pointer & ptr) 24304 { 24305 // get reference to parent of JSON pointer ptr 24306 const auto last_path = ptr.back(); 24307 ptr.pop_back(); 24308 basic_json& parent = result.at(ptr); 24309 24310 // remove child 24311 if (parent.is_object()) 24312 { 24313 // perform range check 24314 auto it = parent.find(last_path); 24315 if (JSON_HEDLEY_LIKELY(it != parent.end())) 24316 { 24317 parent.erase(it); 24318 } 24319 else 24320 { 24321 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this)); 24322 } 24323 } 24324 else if (parent.is_array()) 24325 { 24326 // note erase performs range check 24327 parent.erase(json_pointer::template array_index<basic_json_t>(last_path)); 24328 } 24329 }; 24330 24331 // type check: top level value must be an array 24332 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) 24333 { 24334 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch)); 24335 } 24336 24337 // iterate and apply the operations 24338 for (const auto& val : json_patch) 24339 { 24340 // wrapper to get a value for an operation 24341 const auto get_value = [&val](const std::string & op, 24342 const std::string & member, 24343 bool string_type) -> basic_json & 24344 { 24345 // find value 24346 auto it = val.m_data.m_value.object->find(member); 24347 24348 // context-sensitive error message 24349 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable) 24350 24351 // check if desired value is present 24352 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end())) 24353 { 24354 // NOLINTNEXTLINE(performance-inefficient-string-concatenation) 24355 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val)); 24356 } 24357 24358 // check if result is of type string 24359 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) 24360 { 24361 // NOLINTNEXTLINE(performance-inefficient-string-concatenation) 24362 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val)); 24363 } 24364 24365 // no error: return value 24366 return it->second; 24367 }; 24368 24369 // type check: every element of the array must be an object 24370 if (JSON_HEDLEY_UNLIKELY(!val.is_object())) 24371 { 24372 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val)); 24373 } 24374 24375 // collect mandatory members 24376 const auto op = get_value("op", "op", true).template get<std::string>(); 24377 const auto path = get_value(op, "path", true).template get<std::string>(); 24378 json_pointer ptr(path); 24379 24380 switch (get_op(op)) 24381 { 24382 case patch_operations::add: 24383 { 24384 operation_add(ptr, get_value("add", "value", false)); 24385 break; 24386 } 24387 24388 case patch_operations::remove: 24389 { 24390 operation_remove(ptr); 24391 break; 24392 } 24393 24394 case patch_operations::replace: 24395 { 24396 // the "path" location must exist - use at() 24397 result.at(ptr) = get_value("replace", "value", false); 24398 break; 24399 } 24400 24401 case patch_operations::move: 24402 { 24403 const auto from_path = get_value("move", "from", true).template get<std::string>(); 24404 json_pointer from_ptr(from_path); 24405 24406 // the "from" location must exist - use at() 24407 basic_json const v = result.at(from_ptr); 24408 24409 // The move operation is functionally identical to a 24410 // "remove" operation on the "from" location, followed 24411 // immediately by an "add" operation at the target 24412 // location with the value that was just removed. 24413 operation_remove(from_ptr); 24414 operation_add(ptr, v); 24415 break; 24416 } 24417 24418 case patch_operations::copy: 24419 { 24420 const auto from_path = get_value("copy", "from", true).template get<std::string>(); 24421 const json_pointer from_ptr(from_path); 24422 24423 // the "from" location must exist - use at() 24424 basic_json const v = result.at(from_ptr); 24425 24426 // The copy is functionally identical to an "add" 24427 // operation at the target location using the value 24428 // specified in the "from" member. 24429 operation_add(ptr, v); 24430 break; 24431 } 24432 24433 case patch_operations::test: 24434 { 24435 bool success = false; 24436 JSON_TRY 24437 { 24438 // check if "value" matches the one at "path" 24439 // the "path" location must exist - use at() 24440 success = (result.at(ptr) == get_value("test", "value", false)); 24441 } 24442 JSON_INTERNAL_CATCH (out_of_range&) 24443 { 24444 // ignore out of range errors: success remains false 24445 } 24446 24447 // throw an exception if test fails 24448 if (JSON_HEDLEY_UNLIKELY(!success)) 24449 { 24450 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val)); 24451 } 24452 24453 break; 24454 } 24455 24456 case patch_operations::invalid: 24457 default: 24458 { 24459 // op must be "add", "remove", "replace", "move", "copy", or 24460 // "test" 24461 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val)); 24462 } 24463 } 24464 } 24465 } 24466 24467 /// @brief applies a JSON patch to a copy of the current object 24468 /// @sa https://json.nlohmann.me/api/basic_json/patch/ 24469 basic_json patch(const basic_json& json_patch) const 24470 { 24471 basic_json result = *this; 24472 result.patch_inplace(json_patch); 24473 return result; 24474 } 24475 24476 /// @brief creates a diff as a JSON patch 24477 /// @sa https://json.nlohmann.me/api/basic_json/diff/ 24478 JSON_HEDLEY_WARN_UNUSED_RESULT 24479 static basic_json diff(const basic_json& source, const basic_json& target, 24480 const std::string& path = "") 24481 { 24482 // the patch 24483 basic_json result(value_t::array); 24484 24485 // if the values are the same, return empty patch 24486 if (source == target) 24487 { 24488 return result; 24489 } 24490 24491 if (source.type() != target.type()) 24492 { 24493 // different types: replace value 24494 result.push_back( 24495 { 24496 {"op", "replace"}, {"path", path}, {"value", target} 24497 }); 24498 return result; 24499 } 24500 24501 switch (source.type()) 24502 { 24503 case value_t::array: 24504 { 24505 // first pass: traverse common elements 24506 std::size_t i = 0; 24507 while (i < source.size() && i < target.size()) 24508 { 24509 // recursive call to compare array values at index i 24510 auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i))); 24511 result.insert(result.end(), temp_diff.begin(), temp_diff.end()); 24512 ++i; 24513 } 24514 24515 // We now reached the end of at least one array 24516 // in a second pass, traverse the remaining elements 24517 24518 // remove my remaining elements 24519 const auto end_index = static_cast<difference_type>(result.size()); 24520 while (i < source.size()) 24521 { 24522 // add operations in reverse order to avoid invalid 24523 // indices 24524 result.insert(result.begin() + end_index, object( 24525 { 24526 {"op", "remove"}, 24527 {"path", detail::concat(path, '/', std::to_string(i))} 24528 })); 24529 ++i; 24530 } 24531 24532 // add other remaining elements 24533 while (i < target.size()) 24534 { 24535 result.push_back( 24536 { 24537 {"op", "add"}, 24538 {"path", detail::concat(path, "/-")}, 24539 {"value", target[i]} 24540 }); 24541 ++i; 24542 } 24543 24544 break; 24545 } 24546 24547 case value_t::object: 24548 { 24549 // first pass: traverse this object's elements 24550 for (auto it = source.cbegin(); it != source.cend(); ++it) 24551 { 24552 // escape the key name to be used in a JSON patch 24553 const auto path_key = detail::concat(path, '/', detail::escape(it.key())); 24554 24555 if (target.find(it.key()) != target.end()) 24556 { 24557 // recursive call to compare object values at key it 24558 auto temp_diff = diff(it.value(), target[it.key()], path_key); 24559 result.insert(result.end(), temp_diff.begin(), temp_diff.end()); 24560 } 24561 else 24562 { 24563 // found a key that is not in o -> remove it 24564 result.push_back(object( 24565 { 24566 {"op", "remove"}, {"path", path_key} 24567 })); 24568 } 24569 } 24570 24571 // second pass: traverse other object's elements 24572 for (auto it = target.cbegin(); it != target.cend(); ++it) 24573 { 24574 if (source.find(it.key()) == source.end()) 24575 { 24576 // found a key that is not in this -> add it 24577 const auto path_key = detail::concat(path, '/', detail::escape(it.key())); 24578 result.push_back( 24579 { 24580 {"op", "add"}, {"path", path_key}, 24581 {"value", it.value()} 24582 }); 24583 } 24584 } 24585 24586 break; 24587 } 24588 24589 case value_t::null: 24590 case value_t::string: 24591 case value_t::boolean: 24592 case value_t::number_integer: 24593 case value_t::number_unsigned: 24594 case value_t::number_float: 24595 case value_t::binary: 24596 case value_t::discarded: 24597 default: 24598 { 24599 // both primitive type: replace value 24600 result.push_back( 24601 { 24602 {"op", "replace"}, {"path", path}, {"value", target} 24603 }); 24604 break; 24605 } 24606 } 24607 24608 return result; 24609 } 24610 /// @} 24611 24612 //////////////////////////////// 24613 // JSON Merge Patch functions // 24614 //////////////////////////////// 24615 24616 /// @name JSON Merge Patch functions 24617 /// @{ 24618 24619 /// @brief applies a JSON Merge Patch 24620 /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/ 24621 void merge_patch(const basic_json& apply_patch) 24622 { 24623 if (apply_patch.is_object()) 24624 { 24625 if (!is_object()) 24626 { 24627 *this = object(); 24628 } 24629 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it) 24630 { 24631 if (it.value().is_null()) 24632 { 24633 erase(it.key()); 24634 } 24635 else 24636 { 24637 operator[](it.key()).merge_patch(it.value()); 24638 } 24639 } 24640 } 24641 else 24642 { 24643 *this = apply_patch; 24644 } 24645 } 24646 24647 /// @} 24648 }; 24649 24650 /// @brief user-defined to_string function for JSON values 24651 /// @sa https://json.nlohmann.me/api/basic_json/to_string/ 24652 NLOHMANN_BASIC_JSON_TPL_DECLARATION 24653 std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) 24654 { 24655 return j.dump(); 24656 } 24657 24658 inline namespace literals 24659 { 24660 inline namespace json_literals 24661 { 24662 24663 /// @brief user-defined string literal for JSON values 24664 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/ 24665 JSON_HEDLEY_NON_NULL(1) 24666 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) 24667 inline nlohmann::json operator ""_json(const char* s, std::size_t n) 24668 #else 24669 inline nlohmann::json operator "" _json(const char* s, std::size_t n) 24670 #endif 24671 { 24672 return nlohmann::json::parse(s, s + n); 24673 } 24674 24675 /// @brief user-defined string literal for JSON pointer 24676 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/ 24677 JSON_HEDLEY_NON_NULL(1) 24678 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) 24679 inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n) 24680 #else 24681 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) 24682 #endif 24683 { 24684 return nlohmann::json::json_pointer(std::string(s, n)); 24685 } 24686 24687 } // namespace json_literals 24688 } // namespace literals 24689 NLOHMANN_JSON_NAMESPACE_END 24690 24691 /////////////////////// 24692 // nonmember support // 24693 /////////////////////// 24694 24695 namespace std // NOLINT(cert-dcl58-cpp) 24696 { 24697 24698 /// @brief hash value for JSON objects 24699 /// @sa https://json.nlohmann.me/api/basic_json/std_hash/ 24700 NLOHMANN_BASIC_JSON_TPL_DECLARATION 24701 struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp) 24702 { 24703 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const 24704 { 24705 return nlohmann::detail::hash(j); 24706 } 24707 }; 24708 24709 // specialization for std::less<value_t> 24710 template<> 24711 struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679 24712 { 24713 /*! 24714 @brief compare two value_t enum values 24715 @since version 3.0.0 24716 */ 24717 bool operator()(::nlohmann::detail::value_t lhs, 24718 ::nlohmann::detail::value_t rhs) const noexcept 24719 { 24720 #if JSON_HAS_THREE_WAY_COMPARISON 24721 return std::is_lt(lhs <=> rhs); // *NOPAD* 24722 #else 24723 return ::nlohmann::detail::operator<(lhs, rhs); 24724 #endif 24725 } 24726 }; 24727 24728 // C++20 prohibit function specialization in the std namespace. 24729 #ifndef JSON_HAS_CPP_20 24730 24731 /// @brief exchanges the values of two JSON objects 24732 /// @sa https://json.nlohmann.me/api/basic_json/std_swap/ 24733 NLOHMANN_BASIC_JSON_TPL_DECLARATION 24734 inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) 24735 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 24736 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value) 24737 { 24738 j1.swap(j2); 24739 } 24740 24741 #endif 24742 24743 } // namespace std 24744 24745 #if JSON_USE_GLOBAL_UDLS 24746 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) 24747 using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) 24748 using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) 24749 #else 24750 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) 24751 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) 24752 #endif 24753 #endif 24754 24755 // #include <nlohmann/detail/macro_unscope.hpp> 24756 // __ _____ _____ _____ 24757 // __| | __| | | | JSON for Modern C++ 24758 // | | |__ | | | | | | version 3.11.3 24759 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 24760 // 24761 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 24762 // SPDX-License-Identifier: MIT 24763 24764 24765 24766 // restore clang diagnostic settings 24767 #if defined(__clang__) 24768 #pragma clang diagnostic pop 24769 #endif 24770 24771 // clean up 24772 #undef JSON_ASSERT 24773 #undef JSON_INTERNAL_CATCH 24774 #undef JSON_THROW 24775 #undef JSON_PRIVATE_UNLESS_TESTED 24776 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION 24777 #undef NLOHMANN_BASIC_JSON_TPL 24778 #undef JSON_EXPLICIT 24779 #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL 24780 #undef JSON_INLINE_VARIABLE 24781 #undef JSON_NO_UNIQUE_ADDRESS 24782 #undef JSON_DISABLE_ENUM_SERIALIZATION 24783 #undef JSON_USE_GLOBAL_UDLS 24784 24785 #ifndef JSON_TEST_KEEP_MACROS 24786 #undef JSON_CATCH 24787 #undef JSON_TRY 24788 #undef JSON_HAS_CPP_11 24789 #undef JSON_HAS_CPP_14 24790 #undef JSON_HAS_CPP_17 24791 #undef JSON_HAS_CPP_20 24792 #undef JSON_HAS_FILESYSTEM 24793 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 24794 #undef JSON_HAS_THREE_WAY_COMPARISON 24795 #undef JSON_HAS_RANGES 24796 #undef JSON_HAS_STATIC_RTTI 24797 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 24798 #endif 24799 24800 // #include <nlohmann/thirdparty/hedley/hedley_undef.hpp> 24801 // __ _____ _____ _____ 24802 // __| | __| | | | JSON for Modern C++ 24803 // | | |__ | | | | | | version 3.11.3 24804 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 24805 // 24806 // SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann <https://nlohmann.me> 24807 // SPDX-License-Identifier: MIT 24808 24809 24810 24811 #undef JSON_HEDLEY_ALWAYS_INLINE 24812 #undef JSON_HEDLEY_ARM_VERSION 24813 #undef JSON_HEDLEY_ARM_VERSION_CHECK 24814 #undef JSON_HEDLEY_ARRAY_PARAM 24815 #undef JSON_HEDLEY_ASSUME 24816 #undef JSON_HEDLEY_BEGIN_C_DECLS 24817 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE 24818 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN 24819 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE 24820 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE 24821 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION 24822 #undef JSON_HEDLEY_CLANG_HAS_FEATURE 24823 #undef JSON_HEDLEY_CLANG_HAS_WARNING 24824 #undef JSON_HEDLEY_COMPCERT_VERSION 24825 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK 24826 #undef JSON_HEDLEY_CONCAT 24827 #undef JSON_HEDLEY_CONCAT3 24828 #undef JSON_HEDLEY_CONCAT3_EX 24829 #undef JSON_HEDLEY_CONCAT_EX 24830 #undef JSON_HEDLEY_CONST 24831 #undef JSON_HEDLEY_CONSTEXPR 24832 #undef JSON_HEDLEY_CONST_CAST 24833 #undef JSON_HEDLEY_CPP_CAST 24834 #undef JSON_HEDLEY_CRAY_VERSION 24835 #undef JSON_HEDLEY_CRAY_VERSION_CHECK 24836 #undef JSON_HEDLEY_C_DECL 24837 #undef JSON_HEDLEY_DEPRECATED 24838 #undef JSON_HEDLEY_DEPRECATED_FOR 24839 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL 24840 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ 24841 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED 24842 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES 24843 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS 24844 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION 24845 #undef JSON_HEDLEY_DIAGNOSTIC_POP 24846 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH 24847 #undef JSON_HEDLEY_DMC_VERSION 24848 #undef JSON_HEDLEY_DMC_VERSION_CHECK 24849 #undef JSON_HEDLEY_EMPTY_BASES 24850 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION 24851 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK 24852 #undef JSON_HEDLEY_END_C_DECLS 24853 #undef JSON_HEDLEY_FLAGS 24854 #undef JSON_HEDLEY_FLAGS_CAST 24855 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE 24856 #undef JSON_HEDLEY_GCC_HAS_BUILTIN 24857 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE 24858 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE 24859 #undef JSON_HEDLEY_GCC_HAS_EXTENSION 24860 #undef JSON_HEDLEY_GCC_HAS_FEATURE 24861 #undef JSON_HEDLEY_GCC_HAS_WARNING 24862 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK 24863 #undef JSON_HEDLEY_GCC_VERSION 24864 #undef JSON_HEDLEY_GCC_VERSION_CHECK 24865 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE 24866 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN 24867 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE 24868 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE 24869 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION 24870 #undef JSON_HEDLEY_GNUC_HAS_FEATURE 24871 #undef JSON_HEDLEY_GNUC_HAS_WARNING 24872 #undef JSON_HEDLEY_GNUC_VERSION 24873 #undef JSON_HEDLEY_GNUC_VERSION_CHECK 24874 #undef JSON_HEDLEY_HAS_ATTRIBUTE 24875 #undef JSON_HEDLEY_HAS_BUILTIN 24876 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE 24877 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS 24878 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE 24879 #undef JSON_HEDLEY_HAS_EXTENSION 24880 #undef JSON_HEDLEY_HAS_FEATURE 24881 #undef JSON_HEDLEY_HAS_WARNING 24882 #undef JSON_HEDLEY_IAR_VERSION 24883 #undef JSON_HEDLEY_IAR_VERSION_CHECK 24884 #undef JSON_HEDLEY_IBM_VERSION 24885 #undef JSON_HEDLEY_IBM_VERSION_CHECK 24886 #undef JSON_HEDLEY_IMPORT 24887 #undef JSON_HEDLEY_INLINE 24888 #undef JSON_HEDLEY_INTEL_CL_VERSION 24889 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK 24890 #undef JSON_HEDLEY_INTEL_VERSION 24891 #undef JSON_HEDLEY_INTEL_VERSION_CHECK 24892 #undef JSON_HEDLEY_IS_CONSTANT 24893 #undef JSON_HEDLEY_IS_CONSTEXPR_ 24894 #undef JSON_HEDLEY_LIKELY 24895 #undef JSON_HEDLEY_MALLOC 24896 #undef JSON_HEDLEY_MCST_LCC_VERSION 24897 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK 24898 #undef JSON_HEDLEY_MESSAGE 24899 #undef JSON_HEDLEY_MSVC_VERSION 24900 #undef JSON_HEDLEY_MSVC_VERSION_CHECK 24901 #undef JSON_HEDLEY_NEVER_INLINE 24902 #undef JSON_HEDLEY_NON_NULL 24903 #undef JSON_HEDLEY_NO_ESCAPE 24904 #undef JSON_HEDLEY_NO_RETURN 24905 #undef JSON_HEDLEY_NO_THROW 24906 #undef JSON_HEDLEY_NULL 24907 #undef JSON_HEDLEY_PELLES_VERSION 24908 #undef JSON_HEDLEY_PELLES_VERSION_CHECK 24909 #undef JSON_HEDLEY_PGI_VERSION 24910 #undef JSON_HEDLEY_PGI_VERSION_CHECK 24911 #undef JSON_HEDLEY_PREDICT 24912 #undef JSON_HEDLEY_PRINTF_FORMAT 24913 #undef JSON_HEDLEY_PRIVATE 24914 #undef JSON_HEDLEY_PUBLIC 24915 #undef JSON_HEDLEY_PURE 24916 #undef JSON_HEDLEY_REINTERPRET_CAST 24917 #undef JSON_HEDLEY_REQUIRE 24918 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR 24919 #undef JSON_HEDLEY_REQUIRE_MSG 24920 #undef JSON_HEDLEY_RESTRICT 24921 #undef JSON_HEDLEY_RETURNS_NON_NULL 24922 #undef JSON_HEDLEY_SENTINEL 24923 #undef JSON_HEDLEY_STATIC_ASSERT 24924 #undef JSON_HEDLEY_STATIC_CAST 24925 #undef JSON_HEDLEY_STRINGIFY 24926 #undef JSON_HEDLEY_STRINGIFY_EX 24927 #undef JSON_HEDLEY_SUNPRO_VERSION 24928 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK 24929 #undef JSON_HEDLEY_TINYC_VERSION 24930 #undef JSON_HEDLEY_TINYC_VERSION_CHECK 24931 #undef JSON_HEDLEY_TI_ARMCL_VERSION 24932 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK 24933 #undef JSON_HEDLEY_TI_CL2000_VERSION 24934 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK 24935 #undef JSON_HEDLEY_TI_CL430_VERSION 24936 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK 24937 #undef JSON_HEDLEY_TI_CL6X_VERSION 24938 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK 24939 #undef JSON_HEDLEY_TI_CL7X_VERSION 24940 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK 24941 #undef JSON_HEDLEY_TI_CLPRU_VERSION 24942 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK 24943 #undef JSON_HEDLEY_TI_VERSION 24944 #undef JSON_HEDLEY_TI_VERSION_CHECK 24945 #undef JSON_HEDLEY_UNAVAILABLE 24946 #undef JSON_HEDLEY_UNLIKELY 24947 #undef JSON_HEDLEY_UNPREDICTABLE 24948 #undef JSON_HEDLEY_UNREACHABLE 24949 #undef JSON_HEDLEY_UNREACHABLE_RETURN 24950 #undef JSON_HEDLEY_VERSION 24951 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR 24952 #undef JSON_HEDLEY_VERSION_DECODE_MINOR 24953 #undef JSON_HEDLEY_VERSION_DECODE_REVISION 24954 #undef JSON_HEDLEY_VERSION_ENCODE 24955 #undef JSON_HEDLEY_WARNING 24956 #undef JSON_HEDLEY_WARN_UNUSED_RESULT 24957 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG 24958 #undef JSON_HEDLEY_FALL_THROUGH 24959 24960 24961 24962 #endif // INCLUDE_NLOHMANN_JSON_HPP_ 24963